Dynamische Array vergrössern

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mathias
Beiträge: 5089
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Dynamische Array vergrössern

Beitrag von Mathias »

Wen man eine dynamische Array um ein Element vergrössern will, muss man folgendes schreiben:

Code: Alles auswählen

  SetLength(Items, Length(Items) + 1);
Ist da mit folgendem Schalter eine einfachere Schreibweise möglich ?

Code: Alles auswählen

{$modeswitch arrayoperators}  
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

Sieben
Beiträge: 94
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: i386

Re: Dynamische Array vergrössern

Beitrag von Sieben »

Du könntest doch Insert verwenden, wenn du was anhängen willst...?

Edit: bei 3.2.0 scheint der Schalter auch Standard zu sein.

Benutzeravatar
Winni
Beiträge: 500
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.06, fpc 3.04
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Dynamische Array vergrössern

Beitrag von Winni »

Hi!

Für ein Element gibt es insert, das man überall - nicht nur am Ende - benutzen kann.
Umgekehrt auch delete.

Und endlich auch

Code: Alles auswählen

Array3  :=  Array2 + Array1;
Kann man die sebstgeschnitzen Routinen endlich zum Alteisen packen.

Winni

PS.: Insert ist schlau. Wenn man nicht dauernd rechnen will, das wievielte Element nun am Ende angefügt werden soll, nimmt man Maxint. Er rechnet sich das selbst aus .

wp_xyz
Beiträge: 3462
Registriert: Fr 8. Apr 2011, 09:01

Re: Dynamische Array vergrössern

Beitrag von wp_xyz »

Winni hat geschrieben:
Mi 7. Okt 2020, 20:54
Und endlich auch

Code: Alles auswählen

Array3  :=  Array2 + Array1;
Kann man die sebstgeschnitzen Routinen endlich zum Alteisen packen.
Aber Achtung. Wenn sich jemand eine Vektor-Bibliothek für dynamische Arrays mit überladenem '+' Operator für die Vektor-Addition geschrieben hat, wird er feststellen, dass sie nicht mehr kompiliert, sofern der modeswitch aktiv ist: "Impossible operator overload":

Code: Alles auswählen

program Project1;

{$modeswitch arrayoperators}

uses
  SysUtils;

type
  TVector = array of double;

operator + (a, b: TVector): TVector;     // Compiliert NICHT mit modeswitch
var
  i: Integer;
begin
  if Length(a) <> Length(b) then
    raise Exception.Create('Die zu addierenden Vektoren müssen dieselbe Länge haben.');
  SetLength(Result, Length(a));
  for i := Low(a) to High(a) do
    Result[i] := a[i] + b[i];
end;

var
  a: TVector = (1, 2, 3, 4, 5);
  b: TVector = (10, 20, 30, 40, 50);
  c: TVector;
  i: Integer;
begin
  c := a + b;
  for i := Low(c) to High(c) do
    WriteLn('a[i] = ', a[i]:0:2, ' b[i] = ', b[i]:0:2, ' c[i] = a[i] + b[i] = ', c[i]:0:2);

  ReadLn;
end.
Ich finde, da hätte man sich etwas anderes einfallen lassen können.
Zuletzt geändert von wp_xyz am Mi 7. Okt 2020, 22:56, insgesamt 1-mal geändert.

Benutzeravatar
Winni
Beiträge: 500
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.06, fpc 3.04
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Dynamische Array vergrössern

Beitrag von Winni »

Hi!

Das stimmt!

z.B. hätte man concat überladen können.

Winni

Sieben
Beiträge: 94
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: i386

Re: Dynamische Array vergrössern

Beitrag von Sieben »

Das hat man ja auch noch gemacht...:

http://free-pascal-general.1045716.n5.n ... 31410.html

PascalDragon
Beiträge: 179
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Dynamische Array vergrössern

Beitrag von PascalDragon »

Mathias hat geschrieben:
Mi 7. Okt 2020, 16:18
Wen man eine dynamische Array um ein Element vergrössern will, muss man folgendes schreiben:

Code: Alles auswählen

  SetLength(Items, Length(Items) + 1);
Bitte beachte, dass es meist was Speicherfragmentierung angeht eine schlechte Idee ist Arrays um einzelne Element wachsen zu lassen. Deshalb nutzen Klassen wie TStringList, die intern auch Arrays verwenden, exponentielles Wachstum (sollten wir ja dank diesem Jahr alle Wissen was das ist :P ) für das Array selbst (Stichwort: Capacity), während die eigentliche Länge als Feld in der Klasse gespeichert ist (eventuell wird ab 'ner bestimmten Größe wieder auf lineares Wachstum umgestellt, das hängt aber von der jeweiligen Klasse ab).
Sieben hat geschrieben:
Mi 7. Okt 2020, 16:43
Edit: bei 3.2.0 scheint der Schalter auch Standard zu sein.
Nur im Modus Delphi, da dieses Feature auf Grund von Kompatibilität zu Delphi eingeführt wurde.
wp_xyz hat geschrieben:
Mi 7. Okt 2020, 22:09
Ich finde, da hätte man sich etwas anderes einfallen lassen können.
Beschwer' dich bei den Entwicklern von Delphi, wobei Delphi ja nie globale Überladung von Operatoren unterstützt hat im Gegensatz zu FPC. :roll: Aber genau deswegen haben wir das als Modeswitch gemacht, damit man zumindest unitglobal die Kontrolle darüber hat. Du kannst zum Beispiel im Modus Delphi den Modeswitch wie folgt deaktivieren:

Code: Alles auswählen

{$mode delphi}
{$modeswitch arrayoperators-}
Mit deaktiviertem Modeswitch kannst du allerdings immernoch Concat benutzen, welches in der Tat entsprechend überladen wurde. ;)
FPC Compiler Entwickler

Sieben
Beiträge: 94
Registriert: Mo 24. Aug 2020, 14:16
OS, Lazarus, FPC: Ubuntu Xenial 32, Lazarus 2.0.10, FPC 3.2.0
CPU-Target: i386

Re: Dynamische Array vergrössern

Beitrag von Sieben »

PascalDragon hat geschrieben:
Do 8. Okt 2020, 09:56
Sieben hat geschrieben:
Mi 7. Okt 2020, 16:43
Edit: bei 3.2.0 scheint der Schalter auch Standard zu sein.
Nur im Modus Delphi, da dieses Feature auf Grund von Kompatibilität zu Delphi eingeführt wurde.
Sorry, ich hatte es daraus geschlossen, dass mir auch schon ohne diesen Schalter Insert, Concat und Delete für dynamische Arrays angeboten wurde und der von mir verlinkte Text neben '+' eben auch diese erwähnt. Gibt es irgendwo noch eine Zusammenfassung, was sozusagen 'immer' geht, und welche Erweiterungen den Schalter brauchen?

PascalDragon
Beiträge: 179
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Dynamische Array vergrössern

Beitrag von PascalDragon »

Die Intrinsics gehen immer (es ist nicht wirklich sinnvoll hier was auszuschließen), nur der +-Operator (und eventuell hinzukommende, zukünftige Operator Überladungen) ist an den ModeSwitch ArrayOperators gekoppelt.
FPC Compiler Entwickler

Mathias
Beiträge: 5089
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunc)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Dynamische Array vergrössern

Beitrag von Mathias »

Bitte beachte, dass es meist was Speicherfragmentierung angeht eine schlechte Idee ist Arrays um einzelne Element wachsen zu lassen. Deshalb nutzen Klassen wie TStringList, die intern auch Arrays verwenden, exponentielles Wachstum (sollten wir ja dank diesem Jahr alle Wissen was das ist :P ) für das Array selbst (Stichwort: Capacity), während die eigentliche Länge als Feld in der Klasse gespeichert ist (eventuell wird ab 'ner bestimmten Größe wieder auf lineares Wachstum umgestellt, das hängt aber von der jeweiligen Klasse ab).
Bei meiner Array mit max. 20 Elementen ist dies sicher kein Problem.
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot

PascalDragon
Beiträge: 179
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Dynamische Array vergrössern

Beitrag von PascalDragon »

Wenn du 'ne maximal Größe kennst, ist es eigentlich sogar besser diese Vorzuallokieren und dann am Schluss auf die passende Größe zu verkleinern. Sorgt für weniger Fragmentierung im Speichermanager und du hast (falls der Heap schon stark fragmentiert ist) nur zwei Allokationen statt N.
FPC Compiler Entwickler

Benutzeravatar
Winni
Beiträge: 500
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.06, fpc 3.04
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Dynamische Array vergrössern

Beitrag von Winni »

Hi!

Selbst wenn Du das Maximum nicht kennst, dann kannst Du die Anzahl der Vergrößerungen des arrays reichlich reduzieren.

Code: Alles auswählen

const step = 100;
var ar : array of something;
      someValue: something;
      i : integer = 0;
....
setLength (ar,0);

while i <= BerechneMaximum do
   begin
   if high(ar) <  i then setLength(Length(ar) + step);
   ....
   ar[i] :=  someValue;
   inc(i);
   end;
SetLength(ar,i);
Winni

Antworten