Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Mo Jul 21, 2025 16:45

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 13 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: dynamische Arrays
BeitragVerfasst: Mo Aug 11, 2003 21:45 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jun 24, 2003 19:09
Beiträge: 732
Gibt es eine möglichkeit wie ich aus einem Dynamischen Array ein Element komplett raus schmeißen kann? Ich möchte das Element X eleminiert wird und die nachfolgenden Elemente nachrutschen und keine Lücke Entsteht.
Also z.B. ein Array was mit
0:A
1:B
2:C
3:D
gefüllt ist. Element mit dem Index 1 soll raus geschmissen werden so das bleibt :
0:A
1:C
2:D
gibt es dafür eine Delphi funktion?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Aug 11, 2003 21:50 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
AFAIK bietet dir Delphi keine Funktion um ein Element aus nem dynamischen Array "rauszuschmeissen".Du musst dann halt in ner Schleife alle Elemente eins nach vorne holen (bis zu dem Element das raus soll) und dann die Länge des Arrays um 1 via SetLength verringen.
Wenn du solche Sachen oft machen willst (also in nem dynamischen Array kopieren, löschen, einfügen), solltest du dich evtl. mit dem Objekt "TList" anfreunden.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Aug 11, 2003 21:57 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jun 24, 2003 19:09
Beiträge: 732
genau das wollte ich ebend umgehen.
Bei sehr großen Arrays kann sich ein umsortieren leider recht schnell in der Performance bemerkbar machen.
Da bleibt mir nix weiter als es so zu machen wie ich es bis jetzt immer gemacht habe. Also einfach eine variable mit rein die angibt ob das Element noch genutzt werden soll oder nicht. Ist zwar nicht die beste Lösung aber wesentlich besser als immer komplett neu sortieren.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Aug 11, 2003 22:04 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Sep 23, 2002 19:27
Beiträge: 5812
Programmiersprache: C++
Dann nutz doch die "TList"-Klasse, welche eine sortierbare, veränderbare dynamische Arraylist kapselt.Damit kannst du löschen, verschieben, entfernen und eingügen wie du Lustig bist, ohne das kompliziert und langsam selbst machen zu müssen.

_________________
www.SaschaWillems.de | GitHub | Twitter | GPU Datenbanken (Vulkan, GL, GLES)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Aug 11, 2003 22:26 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jun 24, 2003 19:09
Beiträge: 732
Ich hab die TList Klasse noch nie benutzt :wink:
ich schaus mir aber mal an, wenns nicht zu aufwändig ist kann ich ja noch alles umcoden :)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Aug 11, 2003 22:50 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Okt 26, 2002 17:14
Beiträge: 188
Wohnort: Hannover/Lüneburg
Wenn die Sortierung nicht wichtig ist, reicht es doch einfach das letzte Element an die Stelle zu kopieren, wo das zu löschende Element ist. Dann entweder eine Variable mit der Länge anpassen, um nicht noch mehr Speicherzugriff zu haben und das SetLength() zu vermeiden, welches man dann zu einem späteren Zeitpunkt aufrufen kann (etwa wenn 5 oder mehr leere Elemente am Ende vorhanden sind, oder wenn das programm sonst nichts zu tun hat). Wenn später wieder Elemente hinzugefügt werden müssen spart man sich dann eventuell auch wieder ein SetLength, da das Array noch eine gewisse Größe hat.
Ansonsten ist TList schon besser denke ich, und ansich auch nicht wirklich schwer zu verwenden.

_________________
Thunderman
Bei schwierigen Problemen entscheiden wir uns einfach für die richtige Lösung. Klar?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Aug 11, 2003 22:54 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jun 24, 2003 19:09
Beiträge: 732
hm, das ist auch ne möglichkeit da die Sortierung bei dem wo ich es gerade brauche wirklich egal ist :)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Aug 12, 2003 09:40 
Offline
DGL Member
Benutzeravatar

Registriert: So Dez 29, 2002 10:37
Beiträge: 251
Wohnort: Ulm
man kann es auch so machen, dass du dir einfach die Index-nummern in einer anderen liste speicherst, die gerade nicht benutzt sind und neue werte zunächst in die leerstehenden felder einfügst, bevor du damit beginnst, dein array zu vergrößern..

_________________
http://www.rochus.net


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Aug 12, 2003 10:15 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Da hier ja alle möglichen Methoden aufgezählt werden will ich meine Senf auch mal mit dazu geben. :twisted:

Eine wirklich schnelle aber nicht so leicht zu programmierenden Möglichkeit sind verkettete Listen (einfach oder doppelt). Der Trick dabei ist, dass du hauptsächlich nur mit Pointern arbeitest. Und jedes Element einen Pointer auf das Nächste beinhält. Bei Doppel verketteten Listen auch auf das vorherige (muss aber nicht immer). Wenn du jetzt ein Element löschen oder hinzufügen willst musst du lediglich 2-3 Pointer neu zuweisen. Du musst weder Iterativ alle Elemente durchgehen noch musst du irgendwelche Indizes speichern oder größere Mengen an Speicher bewegen. Allerdings sind solche Listen meist Sinnlos wenn man nur einzelne Zahlen speichern möchte. (Es kommt auch darauf an wie viele Zahlen es sein können etc.) Da durch die Pointer mehr Speicher als bei einem Array oder TList belegt wird.

Hier mal ein kleines Beispiel (mein FPSCalcer aus meinem RenderThread).
Code:
  1. type
  2.   PFPSCalcerItem = ^TFPSCalcerItem;
  3.   TFPSCalcerItem = record
  4.     PrevItem: PFPSCalcerItem;
  5.     NextItem: PFPSCalcerItem;
  6.     Time: Int64;
  7.   end;
  8.  
  9.   TFPSCalcer = class(TObject)
  10.   private
  11.     FCount: Integer;
  12.     FFirst: PFPSCalcerItem;
  13.     FLast: PFPSCalcerItem;
  14.     FMaxTime: Int64;
  15.   public
  16.     procedure AfterConstruction; override;
  17.     procedure BeforeDestruction; override;
  18.    
  19.     property MaxTime: Int64 read FMaxTime write FMaxTime;
  20.     procedure AddTime(Time: Int64);
  21.     function GetAverageFPS: Single;
  22.     procedure ClearAll;
  23.   end;
  24.  
  25. implementation
  26.  
  27. procedure TFPSCalcer.AddTime(Time: Int64);
  28. var
  29.   TempItem: PFPSCalcerItem;
  30. begin
  31.   TempItem := FLast;
  32.   while (Assigned(TempItem)) do begin
  33.     if ((Time - TempItem^.Time) > FMaxTime) then begin
  34.       if (FFirst = FLast)
  35.         then FFirst := TempItem^.PrevItem;
  36.       FLast := TempItem^.PrevItem;
  37.       Dispose(TempItem);
  38.       TempItem := FLast;
  39.       Dec(FCount);
  40.     end
  41.       else Break;
  42.   end;
  43.  
  44.   New(TempItem);
  45.   TempItem^.Time := Time;
  46.   TempItem^.PrevItem := nil;
  47.   TempItem^.NextItem := FFirst;
  48.   if (Assigned(FFirst))
  49.     then FFirst^.PrevItem := TempItem;
  50.   FFirst := TempItem;
  51.   if (not Assigned(FLast))
  52.     then FLast := FFirst;
  53.  
  54.   Inc(FCount);
  55. end;
  56.  
  57. procedure TFPSCalcer.AfterConstruction;
  58. begin
  59.   inherited;
  60.   FFirst := nil;
  61.   FLast := nil;
  62.   FCount := 0;
  63. end;
  64.  
  65. procedure TFPSCalcer.BeforeDestruction;
  66. begin
  67.   inherited;
  68.  
  69.   ClearAll;
  70. end;
  71.  
  72. procedure TFPSCalcer.ClearAll;
  73. var
  74.   Temp: PFPSCalcerItem;
  75. begin
  76.   while (Assigned(FFirst)) do begin
  77.     Temp := FFirst^.NextItem;
  78.     Dispose(FFirst);
  79.     FFirst := Temp;
  80.     Dec(FCount);
  81.   end;
  82.  
  83.   FLast := nil;
  84. end;
  85.  
  86. function TFPSCalcer.GetAverageFPS: Single;
  87. begin
  88.   if (Assigned(FFirst) and Assigned(FLast) and (FCount > 1))
  89.     then Result := (FCount - 1) / (FFirst^.Time - FLast^.Time) * FMaxTime
  90.     else Result := FCount;
  91. end;


Diese Klasse verwendet eine doppelt verkettete Liste mit der es möglich ist in jedem Frame die durchschnitts FPS der letzten Sekunde etc. (MaxTime) zu berechnen. Und alles noch sehr performant.

Bei solchen Listen ist ein indiezieller Zugriff (gib mir mal Element 5) nicht möglich!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Aug 12, 2003 11:28 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Ja verkettete Listen sind das schnellste was man machen kann, wenn man keinen Zugriff über einen Index benötigt. Um die häufige Speicherbelegung zu vermeiden macht man sich dann am besten noch eine zweite verkette Liste mit den leeren Elementen. Wenn man ein Element braucht holt man es sich von der zweiten Liste und wenn man eins freigibt legt man es wieder auf die zweite Liste.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Aug 12, 2003 12:58 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Okt 26, 2002 17:14
Beiträge: 188
Wohnort: Hannover/Lüneburg
Warum hab ich dann eigentlich damals meine Particelengine von Pointer-Listen auf ein Array umgestellt? Naja, wohl weil's in den meisten Beispielen so gemacht wurde. Aber da da meist eh eine feste Particleanzahl reicht geht das ja auch gut - zumal man ja mittlerweile auch mal z-sorting gebrauchen kann.

_________________
Thunderman
Bei schwierigen Problemen entscheiden wir uns einfach für die richtige Lösung. Klar?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Aug 12, 2003 14:54 
Offline
DGL Member
Benutzeravatar

Registriert: Mo Jun 09, 2003 08:09
Beiträge: 98
Also, ich arbeite bei meinem Partikel System auch mit (doppelt, auch wenn es nicht nötig wäre *g*) verketteten Listen (linked lists) und muss sagen, dass ich das so um einiges komfortabler finde, auch ein nicht schlechtes Einsatzgebiet für linked lists ist zum Beispiel die Verwaltung von Geschossen die abgefeuert werden (der liste hinzugefügt), rumfliegen und dann irgendwas treffen (aus der liste entfernt werden).

mfg las


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Aug 12, 2003 15:53 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
las hat geschrieben:
(doppelt, auch wenn es nicht nötig wäre *g*)

Och na ja. Man hat ja so den Vorteil, dass man die Liste in beide Richtungen durchsuchen kann. Und bei Partikeln verhält sich das ja so ähnlich wie bei meinen gemessenen Zeiten. Alles über einem gewissen wert (1 Sek) fliegt weg. Da muss ich ja nicht alle durchsuchen. Der Nachteil ist allerdings der, dass man auf mehrere Pointer achten muss und man sich so leichter einen fehlerhaften Pointer einfängt.
Aber das wird man recht schnell mitbekommen. :twisted:


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 13 Beiträge ] 
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.025s | 19 Queries | GZIP : On ]