![]() |
AW: Zeile aus Stringlist löschen, wie optimieren?
Also löschen dauert wirklich lange, kopieren fast nichts. Ich hab ein Beispiel erstellt mit etwa 1 Mio Daten, davon 10% Leerzeilen. Erstellung etwa 150 ms, Löschung etwa 2 min, Kopiervorgang etwa 100 ms. Also statt löschen der Leerzeilen vielleicht besser kopieren der anderen Zeilen.
Hier das Beispiel mit dem ich gerechnet habe:
Delphi-Quellcode:
//EDIT: sorry, habe beim optimieren in letzter for Schleife downto statt to geschrieben. Die Ergebnisse bleiben aber.
procedure TForm1.Button1Click(Sender: TObject);
const txt = 'qwertzuiopüasdfghjklöäyxcvbnm'; var sl, sl2: TStringList; i, t: Integer; t1, t2: TTime; begin sl := TStringList.Create; sl2 := TStringList.Create; try //--- 1 Mio. Daten mit etw 10% Leerzeilen erstellen / Dauer etwa 150 ms t1 := Now; Cursor := crHourGlass; for i := 1 to 1000000 do if Random(10) = 1 then sl.Add('') else sl.Add(txt); Cursor := crDefault; t2 := Now; t := MilliSecondsBetween(t1, t2); ShowMessage(Format('Count sl: %d | Dauer der Erstellung: %d ms', [sl.Count, t])); //--- 10% Daten (leerzeilen) entfernen / Dauer etwa 120000 ms { t1 := Now; Cursor := crHourGlass; for i := (sl.Count - 1) downto 0 do if sl[i] = '' then sl.Delete(i); Cursor := crDefault; t2 := Now; t := MilliSecondsBetween(t1, t2); ShowMessage(Format('Count sl: %d | Dauert des Löschvorgangs: %d ms', [sl.Count, t])); } //--- 90% Daten (ohne leerzeilen) kopieren / Dauer etwa 300 ms { } t1 := Now; Cursor := crHourGlass; sl2.Capacity := sl.Count; for i := 0 to sl.Count - 1 do //korrigiert <<<<<<<<<<<<< if sl[i] <> '' then sl2.Add(sl[i]); sl.Assign(sl2); sl.Capacity := sl.Count; //Korrektur nach unten Cursor := crDefault; t2 := Now; t := MilliSecondsBetween(t1, t2); ShowMessage(Format('Count sl: %d | Dauer des Kopiervorgangs: %d ms', [sl.Count, t])); finally sl2.Free; sl.Free; end; end; //EDIT2: Apropos Speicher, Capacity sollte am Ende wieder korrigiert werden. |
AW: Zeile aus Stringlist löschen, wie optimieren?
Zitat:
1. es wird ein Pointer aus der Liste entfernt UND die Pointer der nachfolgenden Strings werden verschoben 2. die Referenzen der zukopierenden Strings werden kopiert, und die Referenzzählung wird angesprochen (Stringinhalte werden nicht kopiert) 3. erst wird aus allen Strings/Zeilen EIN großer String gebastelt, dann wird via StringReplace "jeder" doppelte Zeilenumbruch einzeln entfernt (Achtung, bei 3 und mehr aufeinanderfolgenden Zeilenumbrüchen wird nur jeder Zweite entfernt), dabei werden alle nachfolgenden Zeichen jedesmal umkopiert, und dann wird der ganze String wieder in viele Einzelstrings zerlegt Auslesen als TEXT geht nur bei einem Memo (TMemoStrings) schneller, da dort der Text zusammenhängend im RAM liegt. (aber das Löschen der Leerzeilen sollte auch da temporärn einer TStringList erfolgen, da das TMemo arschlangsam ist). Wie kommen die Daten denn in die TStringList? Was am Schnellsten ginge, wäre die Leerstrings garnicht erst aufzunehmen. Also die Add-Methode überschreiben und bei dem ungewollten Leerstring abbrechen. |
AW: Zeile aus Stringlist löschen, wie optimieren?
So chefe stört nicht mehr...
erst einmal vielen Dank für die vielen Rückmeldungen. Zunächst, alle Zeilen müssen vorliegen und erst dann entscheidet sich welche Zeilen gelöscht werden. Sehr oft sind Leerzeilen betroffen und dafür hab ich dann eine Spezialbehandlung. Die Lösung "nicht einlesen" entfällt daher. Die Prüfung auf
Delphi-Quellcode:
hab ich ausprobiert und gefühlt sind da ein paar Sekunden herum gekommen.
Stringlist[i]=''
Die "Kopierlösung" ist auch auf andere Zeileninhalte anwendbar, zusammen mit dem "Auftrennen" scheint das interessant zu werden. Muß ich mal testen. Das wichtigste Problem was ich sehe ist hirbei der Speicherplatzbedarf. Mal ausprobieren. noch mal vielen Dank K-H P.S. z.Zt. arbeite ich mit ca 2,5 Mio Zeilen das fluppt so oder so |
AW: Zeile aus Stringlist löschen, wie optimieren?
Zitat:
wenn das dein Grö´tes Problem solltest du dir alg. Gedanken machen, ob man da nicht was anders Lösen könnte ... |
AW: Zeile aus Stringlist löschen, wie optimieren?
folgendes geht auch (ohne extra Liste)
Delphi-Quellcode:
(Ungetestet) Im Prinzip rennt man die Liste einmal durch und kopiert nur die nichtleeren Zeilen. Nach jedem Kopiervorgang erhöht man die Zielposition j um 1.
Procedure RemoveEmptyLines (aList : TStringList);
Var i,j : Integer; Begin j:=0; for i:=0 to aList.Length-1 do if aList[i]<>'' then begin aList[j] := aList[i]; j := j + 1; end; SetLength(aList,j); End; Braucht kaum/keinen extra Speicher :-) |
AW: Zeile aus Stringlist löschen, wie optimieren?
Ah, da war jemand schneller, habs getestet, ist wirklich schnell.
Delphi-Quellcode:
sl.BeginUpdate;
try i2 := 0; for i := 0 to sl.Count - 1 do begin if sl[i] <> '' then begin sl[i2] := sl[i]; Inc(i2); end; end; for i := sl.Count - 1 downto i2 do sl.Delete(i); finally sl.EndUpdate; end; |
AW: Zeile aus Stringlist löschen, wie optimieren?
Und warum das ganze nicht Ultra-Oldschool ?
Delphi-Quellcode:
Datei wird nur einmal komplett gelesen und der Speicherbedarf ist fürs Einlesen nahezu Null.
procedure bla;
var f: TEXTFILE; s: string; TSL: TStringList; begin TSL:=TStringList.Create; AssignFile(f, 'BLA.TXT'); Reset(f); while not eof(f) do begin ReadLn(f,s); if s <> '' then TSL.Add(s); end; CloseFile(f); end; |
AW: Zeile aus Stringlist löschen, wie optimieren?
Zitat:
|
AW: Zeile aus Stringlist löschen, wie optimieren?
Zitat:
ich war mir nicht sicher ob nicht vielleicht doch die Inhalte kopiert werden! Gruß K-H |
AW: Zeile aus Stringlist löschen, wie optimieren?
Wie siehts mit StringReplace aus? Schonmal probiert wie das abschneidet?
Delphi-Quellcode:
StringReplace(Stringlist.Text,#13#10,'',[rfReplaceAll])
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:36 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz