Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Array-Element löschen (https://www.delphipraxis.net/47539-array-element-loeschen.html)

Taladan 12. Jun 2005 21:11


Array-Element löschen
 
Hallo, ich will in einen dynamsiches Array, in dem ich Records habe, eines raus nehmen und die anderen Nachrücken lasse. Doch irgendwie erhalte ich immer Zugriffsverletzungen oder erhalte nicht das richtige Ergebnis.

Delphi-Quellcode:
procedure TFeldliste.DeleteField(Index: Integer);
var i,l : integer;
begin
  L := length(FListe);
    for i := index to L-1 do begin
      FListe[i].ID := FListe[i+1].id;
      FListe[i].Name := FListe[i+1].Name;
      FListe[i].typ := FListe[i+1].typ;
    end;
  setlength(Fliste, length(fliste)-1);

end;

BenjaminH 12. Jun 2005 21:13

Re: Array-Element löschen
 
Du musst L-2 statt L-1 schreiben, da Array[Length(Array)-1+1] genau um 1 zu groß ist

Robert_G 12. Jun 2005 21:18

Re: Array-Element löschen
 
Wenn du aus deinem Record eine Klasse machst und statt dem Array einen TObjectList (oder eine eigene Ableitung) von TObjectList nimmst dürfte es weniger bis keine Probleme mehr geben. Auf jeden Fall weniger Code. ;)

Christian Seehase 12. Jun 2005 21:20

Re: Array-Element löschen
 
Moin Taladan,

ich weiss ja nicht, wie gross die Liste werden kann, aber ich hatte es vor kurzen auch so gemacht (Kombination dynamisches Array und Record), und auch ganze Bereiche so gelöscht / eingefügt wie Du.
Der Umbau auf TObjectList statt des dynamischen Arrays und einer simplen Klasse (ohne Methoden ;-)) statt des Records hat mir eine Geschwindigkeitssteigerung um den Faktor 30 gebracht (ca. 30 Sekunden statt vorher ca. 1000).

Robert_G 12. Jun 2005 21:27

Re: Array-Element löschen
 
Zitat:

Zitat von Christian Seehase
Der Umbau auf TObjectList statt des dynamischen Arrays und einer simplen Klasse (ohne Methoden ;-)) statt des Records hat mir eine Geschwindigkeitssteigerung um den Faktor 30 gebracht (ca. 30 Sekunden statt vorher ca. 1000).

Das Problem an einem Array ist einfach, dass er keine Klasse ist. :mrgreen:
Deshalb kann man ihn nicht, wie es TList macht, sprungweise wachsen lassen.
Man könnte es, aber es wäre irgendwo ein hässlicher Krampf immer erst eine olle funktion aufzurufen, die das macht. :?
TList selbst ist ja auch nur ein Array, nur halt in einer verwendbaren Kapselung... :)

Taladan 12. Jun 2005 21:30

Re: Array-Element löschen
 
TObjectList <---- Die Antwort auf viele, sehr viele Wutentbrannte Stunden!!! :wall:

Warum hab ich die net schon vorher gekannt. :cry: Gabs die schon in delphi4std :gruebel: ? Ich glaub net... da kamen ja grad die dynamischen Arrays hinzu...

Toll, alles wieder um schreiben. Aber wenigstens danach weniger getippe...

Dumme Frage dazu.

Zitat OH:
Zitat:

Rufen Sie Extract auf, um ein Objekt aus der Liste zu entfernen ohne das Objekt selbst dadurch freizugeben. Nachdem das Objekt entfernt ist, werden alle folgenden Objekte in der Indexposition nach oben verschoben und Count wird herabgesetzt.
Was bedeutet das mti dem Object frei geben? Wird das dann nicht gelöscht? Wenn es aber nicht mehr in der Liste drin ist, wo ist das Object dann? Werd aus der OH nicht so ganz schlau (Ich vermisse die guten alten Beispiele die es in der OH von D4 noch gab

Robert_G 12. Jun 2005 21:33

Re: Array-Element löschen
 
Zitat:

Zitat von Taladan
wenistens danach weniger getippe...

Hier habe ich eine kleine Beispielliste getippt: http://www.delphipraxis.net/internal...=381090#381090
Du könntest einfach TToken durch deine FeldDings-Klasse ersetzen und schon sparst du dir viel rumgecaste. ;)

edit: Da fehlte wohl ein "weni" im Zitat. ;)

jim_raynor 13. Jun 2005 07:15

Re: Array-Element löschen
 
Und falls man doch nicht auf Arrays verzichten kann hilft meine DeleteArray-Funktion:

http://www.delphipraxis.net/internal...ht=deletearray

r2c2 13. Jun 2005 07:45

Re: Array-Element löschen
 
Zitat:

Zitat von Robert_G
TList selbst ist ja auch nur ein Array, nur halt in einer verwendbaren Kapselung... :)

Wirklich? Ich dachte immer n List funktioniert über Pointer: Jedes Item hat n Pointer auf das vorherige und das nächste Item. N dynamisches Array is aber nix anderes als n statisches mit n bisschen Compiler-Magic. Beim Vergrößern wird einfach n neues - statisches - Array erstellt und die Daten reinkopiert. Bei ner List wird n neues Item erstellt und der Pointer des letzten Otems von nil auf die Adresse des neuen Items gesetzt. Oder hab ich das was verpeilt? :gruebel:

mfg

Christian

yankee 13. Jun 2005 07:49

Re: Array-Element löschen
 
Du kannst auch das ganze item hochrollen:
Delphi-Quellcode:
procedure TFeldliste.DeleteField(Index: Integer);
var i,l : integer;
begin
  L := length(FListe);
    for i := index to L-2 do
    begin
      FListe[i] := FListe[i+1];
    end;
  setlength(Fliste, length(fliste)-1);

end;
Das ist kürzer und schneller. Nicht schneller als diese ObjectList, aber dafür kannst du dir das umschreiben sparen. Naja und bei kleinen Listen (<1000 Elemente) wirst du dabei auch keinen Performancenachteil haben, wenn du diese procedure nicht ganz oft hintereiander ausführst.

alzaimar 13. Jun 2005 08:13

Re: Array-Element löschen
 
Wenn Du Move verwendest, geht es noch schneller und ist weniger Code = weniger anfällig:
Delphi-Quellcode:
procedure TFeldliste.DeleteField(Index: Integer);
var i,l : integer;
begin
  L := length(FListe);
  if index < L-1 Then
    move (fListe[Index + 1], fListe [Index], SizeOf (Fliste[0])* (L - Index - 1));
  setlength(Fliste, length(fliste)-1);
End;
Aber ehrlich, ich verstehe nicht, was hier viele 'Experten' gegen eine TList haben. Das ist doch schnell genug und macht das alles schon. Ich kenne nicht allzuviele Anwendungen, die so zeitkritisch sind, das man sich ein TExtremelyFastList bauen müsste.

Wenn ich die vorgefertigten Klassen von Delphi nehme, habe ich doch ein paar Sorgen weniger, weil das schonmal funktioniert... Und wenn ich Performanceprobleme bekomme, dann nehme ich mir einen Profiler. Der zeigt mir die Bottlenecks. Wenn TList der Bösewicht ist, wird ausgetauscht. Aber nur dann...

Robert_G 13. Jun 2005 08:15

Re: Array-Element löschen
 
Zitat:

Zitat von r2c2
Zitat:

Zitat von Robert_G
TList selbst ist ja auch nur ein Array, nur halt in einer verwendbaren Kapselung... :)

Wirklich? Ich dachte immer n List funktioniert über Pointer: Jedes Item hat n Pointer auf das vorherige und das nächste...

TList ist KEINE linked List! ;)

@Topic
Das geht so:
Delphi-Quellcode:
TObjectList.Remove(DeinObject);
Damit wird es auch automatisch freigegeben, solange OwnsObjects True ist. (In meinem BeispielCode ist es True. ;) )
Falls du nur über Index darauf zugreifst könnte man sich eine Ankürzung machen und das hier noch hinzufügen:
Delphi-Quellcode:
   TFeldDingslist = class(TObjectList)
   ...
   public
   ...
      procedure Remove(aIndex: Integer); virtual;
   ...
implementation
...
procedure Remove(aIndex: Integer);
begin
   Remove(Items[aIndex]);
end;

r2c2 13. Jun 2005 10:19

Re: Array-Element löschen
 
[quote="Robert_G"]
Zitat:

Zitat von r2c2
Zitat:

Zitat von Robert_G
TList selbst ist ja auch nur ein Array, nur halt in einer verwendbaren Kapselung... :)

Wirklich? Ich dachte immer n List funktioniert über Pointer: Jedes Item hat n Pointer auf das vorherige und das nächste...

TList ist KEINE linked List! ;)
quote]
Gut, dann hab ich wirklich was verpeilt. Das muss ich mir dann nochmal angucken.

mfg

Christian

Robert_G 13. Jun 2005 20:00

Re: Array-Element löschen
 
Zitat:

Zitat von alzaimar
Aber ehrlich, ich verstehe nicht, was hier viele 'Experten' gegen eine TList haben. Das ist doch schnell genug und macht das alles schon. Ich kenne nicht allzuviele Anwendungen, die so zeitkritisch sind, das man sich ein TExtremelyFastList bauen müsste.

Moin,
ich glaube hier hat keiner was gegen TList gesagt, außer ich in der letzten Zeile des Beitrages hinter dem Link. ;)
Ich habe eigentlich nur aus 2 Gründen etwas gegen TList a) sie steht in Classes.pas und b) sie hat ihre Methoden nicht virtual.
Ich selbst verwende sie nicht sondern eigene Implementierungen, die auf entweder Array oder Listen bzw. Baum -basiert sind.
Da ich diese aber nicht rausrücken will ( :P ) denke ich dass eine TList-Ableitung hier prima ihren Job erfüllt. ;)

Marphy 14. Jun 2005 11:41

Re: Array-Element löschen
 
Hallo,

Zitat:

Zitat von alzaimar
Und wenn ich Performanceprobleme bekomme, dann nehme ich mir einen Profiler. Der zeigt mir die Bottlenecks.

Mal wieder ein wenig OT, frage nur ganz kurz... :mrgreen: Wo kann ich einen günstigen Profiler kaufen bzw. herunterladen? D.h. könnt ihr mir ein paar (Delphi-)Profiler nennen? Danke!

Gruß, Marco :angel2:


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:07 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