Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi TArray - Alternative zu SetLength(..) ? (https://www.delphipraxis.net/179284-tarray-alternative-zu-setlength.html)

Der schöne Günther 24. Feb 2014 18:56

TArray - Alternative zu SetLength(..) ?
 
Ich möchte ein Array erstellen, und das soll bitte x Stellen breit sein. Jeder vernünftige Mensch geht, bei bspw. fünf Stellen hin und sagt
Delphi-Quellcode:
var
   myArray: TArray<Boolean>;
begin
   myArray := TArray<Boolean>.Create();
   SetLength(myArray, 5);
   [...]
end
Meine Motivation ist, dass ich gerne eine Kollektion (wie eine Liste) hätte, und die soll bitte direkt vom Start weg eine bestimmte Länge haben. Ja, man kann hingehen, und nacheinander die beliebige Menge an Elementen hinzufügen.

Wäre es nicht viel eleganter, wenn man "anonym" ein Array mit gleich einer bestimmten Länge erzeugen kann und das Parameter für dem Copy-Konstruktor nimmt?

Delphi-Quellcode:
uses Spring.Collections;
var
   myBooleanList: IList<Boolean>;
begin
   myBooleanList := TCollections.CreateList<Boolean>(
      TArray<Boolean>.Create(False, False, False, False, False)
   );
end;
Das ist schon nahe dran, allerdings muss ich hier die Elemente im Array alle einzeln auflisten. Ich suche also im Endeffekt einen "Konstruktor" für ein Array das mich nicht die Elemente einzeln auflisten lässt, sondern im Endeffekt nur ein
Delphi-Quellcode:
SetLength(..)
macht- Also nur die Anzahl der mit Default-Wert initialisierten Elemente entgegennimmt.

Gibt es da was feines?

Uwe Raabe 25. Feb 2014 00:19

AW: TArray - Alternative zu SetLength(..) ?
 
Bei einem TArray<T> brauchst du den Konstruktor doch gar nicht:

Delphi-Quellcode:
var
   myArray: TArray<Boolean>;
begin
   SetLength(myArray, 5);
   [...]
end

Mavarik 25. Feb 2014 09:12

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249395)
Jeder vernünftige Mensch geht, bei bspw. fünf Stellen hin und sagt
Delphi-Quellcode:
var
   myArray: TArray<Boolean>;
begin
   myArray := TArray<Boolean>.Create();
   SetLength(myArray, 5);
   [...]
end
[/Delphi]

Jeder vernünftige Mensch... LOL

wir wäre es mit

Delphi-Quellcode:
var
   MyArray : Array[0..4] of Boolean;
Ich dachte so machen das vernünftige Menschen... :stupid:

OK Spass beiseite.

Kannst Du mal erklären wofür und was Du vor hast?

Mavarik

Der schöne Günther 25. Feb 2014 09:37

AW: TArray - Alternative zu SetLength(..) ?
 
Ich möchte eine Liste anlegen. Beispielsweise die Standard RTL-Liste
Delphi-Quellcode:
System.Generics.Collections.TList
. Oder eine
Delphi-Quellcode:
Spring.Collections.IList
.

Diese Liste soll vom Start weg 20 Einträge haben. Booleans, Floats, irgendwas.

Das sieht dann so aus
Delphi-Quellcode:
uses System.Generics.Collections;
const
   numItems:       Integer =   20;
   stdItemValue:    Integer =   0;
var
   myList: TList<Integer>;
   itemNo: Integer;
begin
   myList := TList<Integer>.Create();
   
   for itemNo := 0 to Pred(numItems) do
      myList.Add(stdItemValue);
      
end;
Ich denke, das geht besser. Einer Liste kann man bspw. schön sagen "Füge alle Einträge dieses Arrays hinzu":

Delphi-Quellcode:
uses System.Generics.Collections;
const
   numItems:     Integer =  20;
   stdItemValue:  Integer =  0;
var
   myArray:   TArray<Integer>;
   myList:    TList<Integer>;

   itemNo:    Integer;
begin

   // Array erstellen und füllen
   myArray := TArray<Integer>.Create();
   SetLength(myArray, numItems);

   for itemNo := 0 to Pred(numItems) do
      myArray[itemNo] := stdItemValue;

   // Liste aus Array erstellen
   myList := TList<Integer>.Create();
   myList.AddRange(myArray);

   // Mit Spring.Collections.IList ginge auch
   // myList := TCollections.CreateList<Integer>(myArray);

end;
Und ich habe das Gefühl, in der Richtung lässt sich das arg zusammenkürzen. Wenn absolut feststeht, dass es immer fünf Elemente sind, kann ich, dank
Delphi-Quellcode:
TArray<>
ja schon den hier machen:

Delphi-Quellcode:
myList.AddRange( TArray<Integer>.Create(0, 0, 0, 0, 0) );
.

Ich hätte jetzt gerne eine Art
Delphi-Quellcode:
TArray<Integer>.Create(elementCount: Integer)
.


Die erste Idee war, einfach einen Record Helper für [Delphi]TArray<T>[/Delphi zu basteln, aber Helferklassen dürfen anscheinend nicht generisch sein.

Während ich das hier tippe fiel mir die nie genutzte, nicht generische Klasse
Delphi-Quellcode:
TArray
aus
Delphi-Quellcode:
System.Generics.Collections
ein:
Wenn ich mir eine winzige Helferklasse mit
Delphi-Quellcode:
   TArrayHelper = class helper for System.Generics.Collections.TArray
      class function CreateArray<T>(const itemCount: Integer): TArray<T>;
   end;
baue kann ich eigentlich schon relativ zufrieden sein. Jetzt kann ich einfach sagen

Delphi-Quellcode:
myList.AddRange( TArray.CreateArray<Integer>(12345) );
bzw.

Delphi-Quellcode:
myList := TCollections.CreateList<Integer>( TArray.CreateArray<Integer>(5) );
Genau das wollte ich. Auch wenn es schon an den Rand des noch komfortabel lesbaren kommt.

sx2008 25. Feb 2014 09:39

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249395)
... dass ich gerne eine Kollektion (wie eine Liste) hätte

Collections braucht man in Delphi nur, wenn man die Collection im Objektinspektor editieren möchte (oder den Persistenzmechanismus von Delphi ausnützen möchte).
Damit ist das Anwendungsgebiet von Collections die Komponentenentwicklung.

Um eine hohe Anzahl von Booleans speichersparend zu verwalten eignet sich die Klasse TBits.

Der schöne Günther 25. Feb 2014 13:23

AW: TArray - Alternative zu SetLength(..) ?
 
Ich habe weder eine "hohe Anzahl", noch muss ich dringend Speicher sparen. Ist doch nicht verboten, seine Booleans in eine Liste zu packen?

Furtbichler 25. Feb 2014 15:18

AW: TArray - Alternative zu SetLength(..) ?
 
Delphi-Quellcode:
Const
  MyList : Array [0..4] Of Boolean = (false,true,false,true,false);
Ist zwar nur ein Array, aber immerhin.

Jonas Shinaniganz 25. Feb 2014 15:51

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Ich hätte jetzt gerne eine Art TArray<Integer>.Create(elementCount: Integer) .
Dann schreib dir doch so einen Klasse.

Delphi-Quellcode:
uses System.Generics.Collections;

TMyList<T> = class TList<T>
...
constructor Create(T...; Elements : Integer)


begin
    inherited Create(T...);
   
    for itemNo := 0 to Pred(Elements) do
       Add(X);
end;
??

TiGü 25. Feb 2014 16:55

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249395)
Ich möchte ein Array erstellen, und das soll bitte x Stellen breit sein.

Meine Motivation ist, dass ich gerne eine Kollektion (wie eine Liste) hätte, und die soll bitte direkt vom Start weg eine bestimmte Länge haben.

Du möchtest "reservieren"?
Delphi-Quellcode:
var
  MyList : TList<Boolean>;
begin
  MyList := TList<Boolean>.Create;
  MyList.Capacity := 20; // jetzt sind 20 Elemente drin, in diesem Fall ist der Wert der Items gleich false
  MyList.Free;
end;
Aus dem Debugger:
Code:
MyList   ((False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False), 0, Pointer($666A2C) as {System.Generics.Defaults}IComparer<System.Boolean>, (nil,nil), $2A42880)

Furtbichler 25. Feb 2014 17:20

AW: TArray - Alternative zu SetLength(..) ?
 
Günthers lustige Ratestunde.

Der schöne Günther 25. Feb 2014 17:40

AW: TArray - Alternative zu SetLength(..) ?
 
Herzlich Willkommen dazu.


Wie gesagt, ich wollte einfach nur anonym ein Array mit X Elementen haben. Bastel ich mir halt einfach selbst was an TArray dran. Dachte, da könnte es vielleicht schon so etwas geben.

Mavarik 26. Feb 2014 11:10

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249583)
Herzlich Willkommen dazu.


Wie gesagt, ich wollte einfach nur anonym ein Array mit X Elementen haben. Bastel ich mir halt einfach selbst was an TArray dran. Dachte, da könnte es vielleicht schon so etwas geben.

Wir könnten Sicherlich besser helfen, wenn wir einen Sinn darin sehen würden...
Worin liegt der Nutzen eine Liste mit X Elementen "Müll" zu füllen?

Entweder habe ich die Daten Statisch im Source als Const oder lese es aus einer Resource oder aus einer Datei/Datenbank...

Lass einfach das Generics geraffel weg und nimm einen Fillchar...

Mavarik

Der schöne Günther 26. Feb 2014 11:16

AW: TArray - Alternative zu SetLength(..) ?
 
Danke für die gut gemeinte Hilfe.

Ich hätte einfach nur fragen sollen "Gibt es schon etwas, womit ich anonym ein Array mit einer bestimmten Länge erstellen kann?". Dann hätte jemand gesagt "Nö. Bau dir halt selber was.". Und dann wäre es das schon gewesen.

Mavarik 26. Feb 2014 11:28

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249698)
Danke für die gut gemeinte Hilfe.

Ok wir verbuchen es als Beschäftigungstherapie. :stupid:

Bjoerk 26. Feb 2014 11:36

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249698)
Ich hätte einfach nur fragen sollen "Gibt es schon etwas, womit ich anonym ein Array mit einer bestimmten Länge erstellen kann?". Dann hätte jemand gesagt "Nö. Bau dir halt selber was.". Und dann wäre es das schon gewesen.

Falls du dir was selber stricken möchtest, dann kannst du dir z.B. anschauen wie TList Capacity setzt (Capacity >= Count). Das interne Array dort muß übrigens nicht unbedingt Pointer auf Pointer sein.

Der schöne Günther 26. Feb 2014 11:44

AW: TArray - Alternative zu SetLength(..) ?
 
Das mit der
Delphi-Quellcode:
TList
war ja nur ein Beispiel. Ein Array mit x Elementen wollte ich gerne haben um es irgendwo reinzustecken:

Delphi-Quellcode:
function gibArray<T>(const elementCount: Integer): TArray<T>;
begin
   SetLength(Result, elementCount);
end;
Meine Frage war einfach nur, ob es so etwas schon gibt.

Auf jeden Fall vielen Dank an alle beteiligten! :-)

Stevie 26. Feb 2014 12:13

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249704)
Das mit der
Delphi-Quellcode:
TList
war ja nur ein Beispiel. Ein Array mit x Elementen wollte ich gerne haben um es irgendwo reinzustecken:

Delphi-Quellcode:
function gibArray<T>(const elementCount: Integer): TArray<T>;
begin
   SetLength(Result, elementCount);
end;
Meine Frage war einfach nur, ob es so etwas schon gibt.

Auf jeden Fall vielen Dank an alle beteiligten! :-)

Du wirst ja irgendwas mit dem Ergebnis dieser Methode machen wollen, gell?
Zum Beispiel es einer Variable vom Typ TArray<T> zuweisen? Warum also nicht gleich
Delphi-Quellcode:
SetLength(meinArray, 5)
aufrufen?
Klar, das eine ist eine Funktion, die dir ein Array einer bestimmten Länge zurückliefert, was du rein theoretisch direkt an eine andere Methode übergeben kannst
(wobei ich hierbei den Nutzen davon bezweifeln möchte, ein Array mit x Einträgen, die aber nicht befüllt sind, zu übergeben).
Und das andere eine Methode mit einem var Parameter, der die Größe eines zuvor deklarierten dynamischen Arrays setzt.

Darum die konkrete Frage, wozu du so etwas haben möchtest.

Wie bereits gesagt, ich bezweifel den praktischen Nutzen, nur um es woanders hin übergeben zu können, wenn die Elemente ja alle "leer" (
Delphi-Quellcode:
Default(T)
) sind.

Kannst du ein praktisches Beispiel benennen, wo man ein dynamisches Array mit einer bestimmten Größe aber leeren Einträgen irgendwo by Value (also nicht als var, denn das geht ja nicht mit einem Result einer Funktion) übergeben sollte?

P.S.
Bei diesem Code kräuseln sich mit die Fußnägel hoch:
Delphi-Quellcode:
var
  myBooleanList: IList<Boolean>;
begin
  myBooleanList := TCollections.CreateList<Boolean>(
    TArray<Boolean>.Create(False, False, False, False, False)
   );
end;
Besser:
Delphi-Quellcode:
var
  myBooleanList: IList<Boolean>;
begin
  myBooleanList := TCollections.CreateList<Boolean>([False, False, False, False, False]);
end;

Der schöne Günther 26. Feb 2014 12:24

AW: TArray - Alternative zu SetLength(..) ?
 
Ob man etwas wirklich so machen "sollte" - Darüber werden wir uns im Endeffekt doch wieder streiten.

Ganz konkretes Beispiel: Ich möchte eine
Delphi-Quellcode:
Spring.Collections.IList<TIrgendeinTyp>
haben.

Bei
Delphi-Quellcode:
TCollections.CreateList<>(const values: Array of TIrgendeinTyp)
kann ich ein Array mit x Elementen angeben und meine Liste beinhaltet direkt diese Elemente.

Hier sind die meisten schon ausgestiegen, das sei ja totaler Quatsch und überhaupt.
Vielleicht ist bei meinen Pillen etwas durcheinander gekommen, aber ich finde, das entfernt sich zu weit von der eigentlichen Frage und tut eigentlich auch überhaupt nichts zur Sache.


Ja, ich kann einfach ein Array nehmen, SetLength() darauf machen und dieses Array jetzt da hineinstecken. Ich kann auch x mal Add() auf meiner Liste machen. Ich wollte mir einfach nur die Array-Variable bzw. die Zähl-Variable für das "x mal" sparen.

Also einfach sagen
Delphi-Quellcode:
CreateList<TIrgendeinTyp>( TArray.createArray<TIrgendeinTyp>(35) );
.

Und das schmeckt sicher jedem anders.

Mavarik 26. Feb 2014 12:32

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249709)
Also einfach sagen
Delphi-Quellcode:
CreateList<TIrgendeinTyp>( TArray.createArray<TIrgendeinTyp>(35) );
.

Ja aber wofür? Das hat doch echt NULL nutzen..

Der schöne Günther 26. Feb 2014 12:36

AW: TArray - Alternative zu SetLength(..) ?
 
Ich komme wirklich nicht hinterher :?
Woran erkennst du das? Du kannst doch nicht riechen, wofür die Liste gut ist oder was ich damit mache.

Oder etwa doch? :shock:

Stevie 26. Feb 2014 12:46

AW: TArray - Alternative zu SetLength(..) ?
 
Als Liste sehe ich hier auch keinen Nutzen. Was eher irgendwo mal nützlich sein könnte, wäre sowas, wie Enumerable.Repeat oder Enumerable.Range.
Beides werde ich evtl noch bei
Delphi-Quellcode:
Spring.Collections.TCollections
hinzufügen.

Der schöne Günther 26. Feb 2014 12:59

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Enumerable.Repeat<T>(T wert, int Count)
Exakt, ganz genau das ist, was ich wollte und im Endeffekt ja auch mache. Da es in den Spring4D-Collections ja noch nicht drinsteckt, wollte ich halt im Konstruktor einfach so ein Array reinstecken.

Tue ich ja auch. Ich bin glücklich. Und trotzdem kommen alle, und wollen mich in die Zwangsjacke stecken :-(

Mavarik 26. Feb 2014 14:34

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249716)
Und trotzdem kommen alle, und wollen mich in die Zwangsjacke stecken :-(

Ja klar, weil Du es nicht geschafft hast ein einziges mal uns eine Anwendung dafür zu nennen! Oder ist das ein Geheimnis?

QuickAndDirty 3. Mär 2020 10:03

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Mavarik (Beitrag 1249724)
Zitat:

Zitat von Der schöne Günther (Beitrag 1249716)
Und trotzdem kommen alle, und wollen mich in die Zwangsjacke stecken :-(

Ja klar, weil Du es nicht geschafft hast ein einziges mal uns eine Anwendung dafür zu nennen! Oder ist das ein Geheimnis?

Ich meine, wenn er sagt was er gerne hätte, dann ist doch total egal ob er dazu auch eine Anwendung nennt oder ob er sie Geheimhält.
Wieso, wenn man die Lösung weiß, diese verschweigen, nur weil man keinen überzeugenden Verwendungszweck genannt bekommt?
Sehr verwirrend.
Zitat:

Zitat von Der schöne Günther (Beitrag 1249716)
Und trotzdem kommen alle, und wollen mich in die Zwangsjacke stecken :-(

Hast du dir mal deinen Nickname angeschaut? :)

Der schöne Günther 3. Mär 2020 10:11

AW: TArray - Alternative zu SetLength(..) ?
 
Viele Jahre sind seitdem vergangen, und ich blicke zurück auf mein TArray.Construct<T>(..) das ich mir nach dieser feurigen Diskussion hier wohl gebaut haben muss. Anwendungsfälle hatte ich in der Zwischenzeit viele, insbesondere für Tests.

Ich bereue nichts.

himitsu 3. Mär 2020 11:16

AW: TArray - Alternative zu SetLength(..) ?
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1249527)
Ich habe weder eine "hohe Anzahl", noch muss ich dringend Speicher sparen. Ist doch nicht verboten, seine Booleans in eine Liste zu packen?

Nja, im Grunde hat eine TList<T> intern auch nur ein TArray<T> drinnen, auf das man mit deren Funktionen (Add/Insert/Delete/...) zugreifen kann.

Gut, wenn man anfängt mittendrin Booleans einzufügen oder rauszulöschen, ohne einen Zusammenhang zu irgendwas, oder der Zusammenhang zu einer anderen unabhängigen Liste, dann würde mit eher der Gedanke zu sowas die einem TDictionary<Irgendwas,Boolean> schwelgen.

PS: Delphi-Referenz durchsuchenTBits ... das ist eine Liste von Bits, also 1-Bit-Boleans. :stupid:

Rollo62 3. Mär 2020 11:39

AW: TArray - Alternative zu SetLength(..) ?
 
Was genau Du willst kann ich leider auch nicht nachvollziehen, aber vielleicht geht das hier in deine Richtung.
Man könnte solche Initialisierungen evtl. so machen, und die eigentlichen Settings damit separat kapseln.

Delphi-Quellcode:
var
  LVar1 : TWasAuchImmer;
  LVar2 : TWasAuchImmer;
  LVar3 : TWasAuchImmer;

  Init_FuerAufgabe1( LVar1 );
  Init_FuerAufgabe2( LVar2 );
  Init_FuerAufgabe3( LVar1 );
...


procedure Init_FuerAufgabe1( var AVar : TWasAuchImmer);
begin
    if not Assigned( AVar ) then
        AVar := TWasAuchImmer.Create;

    AVar.Items.Clear;
    AVar.Items.Add( false );
    AVar.Items.Add( true );
    AVar.Items.Add( false );
    AVar.Items.Add( false );
    AVar.Items.Add( false );
end;



procedure Init_FuerAufgabe2( var AVar : TWasAuchImmer);
begin
    if not Assigned( AVar ) then
        AVar := TWasAuchImmer.Create;

    AVar.Items.Clear;
    AVar.Items.Add( false );
    AVar.Items.Add( true );
    AVar.Items.Add( false );
    AVar.Items.Add( true);
    AVar.Items.Add( false );
end;


procedure Init_FuerAufgabe3( var AVar : TWasAuchImmer);
begin
    if not Assigned( AVar ) then
        AVar := TWasAuchImmer.Create;

    AVar.Items.Clear;
    AVar.Items.Add( true );
    AVar.Items.Add( true );
    AVar.Items.Add( false );
    AVar.Items.Add( false );
    AVar.Items.Add( false );
end;

Der schöne Günther 3. Mär 2020 12:10

AW: TArray - Alternative zu SetLength(..) ?
 
Ich gebe nochmal ein Beispiel.

Ganz klassisch:

Delphi-Quellcode:
procedure p();
var
   a, b: TArray<Single>;
   arrayIndex: Integer;
begin
   SetLength(a, 100);
   for arrayIndex := Low(a) to High(a) do
      a[arrayIndex] := 10.0;
   
   SetLength(b, 50);
   for arrayIndex := Low(b) to High(b) do
      b[arrayIndex] := 20.0;
      
   ProcessData(a, b);
end;
Mir war das zu lang. Ich wollte lieber so etwas haben:
Delphi-Quellcode:
procedure p()
begin
   ProcessData(
      TArray.Construct<Single>(100, 10.0),
      TArray.Construct<Single>(50, 20.0)
   );
end;

Ich bekam es. Und sah dass es gut war. Ende 😉

himitsu 3. Mär 2020 13:22

AW: TArray - Alternative zu SetLength(..) ?
 
Ja, im Grunde wäre es zu praktisch, wenn der Array-Helper im Delphi bereits eine Create-Methode hätte, wo man eine Länge mit optionaler Initialisierung angeben könnte.


Nach SetLength ist der neue Speicher mit 0 initialisiert,
beim Boolean-Array macht ein FillChar mit 1 bzw. mit Ord(True) ganz viele True daraus.

Delphi-Quellcode:
uses
  AnsiStrings;

procedure TForm1.FormCreate(Sender: TObject);
var
  a: TArray<Single>;
begin
  //SetLength(a, 100);
  //for i := Low(a) to High(a) do
  //  a[i] := 10.0;

  SetLength(a, 100);
  Move(PAnsiChar(DupeString(#0#0' A', 100))^, a[0], 100*4); // oder FillChar für ByteTypen
oder
Delphi-Quellcode:
SetLength(a, 100); for i := 0 to High(a) do a[i] := 10.0;
:stupid:


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:27 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz