Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi TStringlist, THashedStringlist gibts nichts schnelleres?? (https://www.delphipraxis.net/149517-tstringlist-thashedstringlist-gibts-nichts-schnelleres.html)

Franzelchen 23. Mär 2010 12:12


TStringlist, THashedStringlist gibts nichts schnelleres??
 
Hallo DPler,

TStringlist, THashedStringlist gibts nichts schnelleres?? und genauso komfortables. Ich meine die Funktionen Stringlist.LoadfromFile .SavetoFile .Strings[i].

himitsu 23. Mär 2010 12:41

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Franzelchen
Ich meine die Funktionen .LoadfromFile .SavetoFile

Nein, denn überall muß die Datei eingelesen, zerlegt und die Strings im "RAM" abgelegt werden.
Und bei der THashedStringList muß zusätzlich noch pro String ein Hash beechnet werden.

.Strings[i] ist bei der "normalen" StringList oder bei einem Array am schnellsten, da man dort direkt via Index zugreifen kann.
Bei der HashedStringList, SkipList und ihren Verwandten kommt es dann darauf an, ob neben der HashMap auch noch eine Index-Liste existiert.

Das schnellste LoadfromFile wäre alles in EINEN String oder einen MemoryStream zu lesen, aber dann gibt es keinen Index und man kann nicht direkt via .Strings[i] zugreifen.

PS: Wenn nur via .Strings[i] zugegriffen wird, dann ist die THashedStringList vollkommen überflüssig, weil sie auf eine Stringsuche ausgelegt ist und nicht für einen Indexzugriff.

Franzelchen 23. Mär 2010 12:46

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Natürlich gibt es die vielbeschworene Skiplist. Diese würde sogar (vgl. Suchverfahren mit Beispielen) meine Dateigröße abdecken( ca.40 000 Datensätze) aber wie verwende ich die Skiplist. In allen Beispielen wird die Skiplist mit Zufallsstrings aufgefüllt aber nie mit echten Daten.
Also wie bekomme ich eine Datei in die Skiplist (LoadfromFile) und wie kann ich mit der Skiplist arbeiten (Strings[i]) und wie Speichere ich die Daten der Skiplist (SaveToFile).

himitsu 23. Mär 2010 12:52

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Franzelchen
Natürlich gibt es die vielbeschworene Skiplist.

Ließ bitte mal alles, auch das, welches ich noch nacheditiert hab.

Wenn du nur .LoadFromFile .SavetoFile und .Strings[i] verwendest, dann ist TStringList mitunder das Schnellste.

Schneller geht es nur (wenn die Liste nicht im Programm verändert werden soll oder wenn SaveToFile etwas länger dauern darf), wenn man alles an einem Stück einließt und dann nur eine Indexliste mit den Stringanfängen/-längen anlegt und wenn auf alle Strings/Zeilen maximal ein-/zweimal zugegriffen wird oder wenn einem der Speicherverbrauch für eine doppelte Datenhaltung egal ist.

Franzelchen 23. Mär 2010 13:05

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von himitsu

Wenn du nur .LoadFromFile .SavetoFile und .Strings[i] verwendest, dann ist TStringList mitunder das Schnellste.

Da ich außer dem genannten nur noch .sort verwende habe ich also Pech gehabt. Schade.

himitsu 23. Mär 2010 13:23

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Wenn du "sehr oft" etwas ändern/einfügen/löschen und auch sortieren würdest und "selten" via .Strings[i] zugreifst, dann wäre eine HashList ('ne SkipList ist auch eine) insgesamt schon schneller. :angel2:

Franzelchen 23. Mär 2010 13:31

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Ich benötige die Stringliste nur zum sortieren,laden,speichern und sehr häufig die .Strings[i] Funktion. Das sortieren benötigt die geringste Zeit, es wäre schon ein erheblicher Fortschritt wenn es einen Weg gäbe der die .Strings[i] Verarbeitung beschleunigen würde.

himitsu 23. Mär 2010 13:48

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Delphi-Quellcode:
property Strings[Index: Integer]: string read Get write Put; default;

function TStringList.Get(Index: Integer): string;
begin
  if Cardinal(Index) >= Cardinal(FCount) then
    Error(@SListIndexError, Index);
  Result := FList^[Index].FString;
end;
Wie gesagt, .Strings von TStringList (TStrings) ist schon ein direkter Zugriff und schneller als direkt geht es einfach nicht,
außer man nimmt direkt ein dynamisches Array ohne aktivierte Indexprüfung. (siehe Compiler-Schalter oder Projektoptionen)

alzaimar 23. Mär 2010 14:00

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Franzelchen
Natürlich gibt es die vielbeschworene Skiplist. Diese würde sogar (vgl. Suchverfahren mit Beispielen) meine Dateigröße abdecken( ca.40 000 Datensätze) aber wie verwende ich die Skiplist. In allen Beispielen wird die Skiplist mit Zufallsstrings aufgefüllt aber nie mit echten Daten.

Wo ist denn da nun bitte der Unterschied?
Delphi-Quellcode:
MyList.Add(MyKeyString, MyData)
Wo ist eigentlich dein Problem? Selbst 40.000 Datensätze sind doch in Null,Nix eingelesen über eine TStringlist eingelesen. Der Zugriff erfolgt auch schnell genug, und selbst die Suche in einer sortieren Stringlist wäre doch kein Problem, oder?

Zeig uns doch mal den Code, bei dem Du Performanceprobleme bekommst.

Wenn Du noch eine Nanosekunde rausholen willst, dann vergiss die TStringlist und verwende ein ARRAY OF STRING. Das vermeidet den Umweg über einen Getter-Aufruf. Aber verwende keine dynamischs Array weil das ja wieder erst umständlich und performancefressend dereferenziert werden muss :gruebel: :zwinker:

Delphi-Quellcode:
Type
  TTheMotherOfAllSchnelleStringZugriffe = ARRAY [0..39999] OF STRING;
Oder geht es noch schneller?

Franzelchen 23. Mär 2010 15:27

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Hier der Code

Delphi-Quellcode:
begin
Screen.Cursor := crHourGlass;
startZeit := now;
  x:=tstringlist.Create;
  x.LoadFromFile('C:\DB\DatenTest.tmp');

  x.Text:= StringReplace(x.Text,'ß','SSSSSSS', [rfReplaceAll]);
  x.Sort;
  x.Text:= StringReplace(x.Text,'SSSSSSS','ß',[rfReplaceAll]);

  x.SaveToFile('sortiert.txt');


// ab hier wird es extrem langsam

  a:=0;
  stringgrid1.RowCount:=1;           //löscht überflüssige Leerzeilen
  for b:=0 to x.count-1 do
  begin
   progressbar6.Max:= x.Count-1 ;
   progressbar6.position:=b ;
   progressbar6.Update;
      if b>0 then begin
       if x.strings[b]=x.Strings[b-1] then begin
          StringGrid1.cells[1,a]:= inttostr(strtoint (StringGrid1.cells[1,a])+1)
      end else begin
               inc(a);
               StringGrid1.cells[1,a] := '1';
               StringGrid1.cells[0,a] := x.strings[b];
               StringGrid1.RowCount := StringGrid1.RowCount+1;
               end;
      end else begin
               StringGrid1.cells[0,a]:=x.Strings[b];
               StringGrid1.cells[1,a]:='1';
      end;
   end;
 x.Destroy;
StopZeit := Now;
StatusBar6.Panels[1].Text :='SuchZeit : '+ FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ;
Screen.Cursor := crDefault;
end;
Dieser Text dauert auf meinem langsamen Rechner ca. 17 sec. Ab markierter Stelle allein etwa 12-13 sec.
Der Rest der Zeit geht für das Sortieren drauf.

Zitat:

Zitat von alzaimar
Delphi-Quellcode:
MyList.Add(MyKeyString, MyData)

MyKeyString??
Was soll denn das sein? Immer wieder fällt mir Key mit der Add funktion auf aber wozu der Key da ist habe ich keine Ahnung

Muetze1 23. Mär 2010 15:33

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Es ist ein Wunder, dass er nur so lange braucht. Der Code ist mehr als unperformant und zudem auch sehr unsicher.

1. Zuweisen und Lesen von der Eigenschaft .Text baut den String jedesmal erneut auf bzw. parst ihn neu.
2. try/finally fehlt komplett
3. .RowCount in einer Schleife in einzelnen Schritten zu erhöhen bzw. zu verringern kostet viel Zeit.
4. Du setzt einen neuen Wert bei der Progressbar und zwingst ihn sofort neu zu zeichnen. Somit wird das Zeichnen der Progressbar mit jedem Durchlauf innerhalb der Schleife getan und kostet somit noch mehr Zeit.

Grundlegend: Trenne Daten von der Oberfläche!

Franzelchen 23. Mär 2010 15:50

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Bitte wie?? was?

Zitat:

Zitat von Muetze1
Es ist ein Wunder, dass er nur so lange braucht. Der Code ist mehr als unperformant und zudem auch sehr unsicher.

1. Zuweisen und Lesen von der Eigenschaft .Text baut den String jedesmal erneut auf bzw. parst ihn neu.
2. try/finally fehlt komplett
3. .RowCount in einer Schleife in einzelnen Schritten zu erhöhen bzw. zu verringern kostet viel Zeit.
4. Du setzt einen neuen Wert bei der Progressbar und zwingst ihn sofort neu zu zeichnen. Somit wird das Zeichnen der Progressbar mit jedem Durchlauf innerhalb der Schleife getan und kostet somit noch mehr Zeit.

Grundlegend: Trenne Daten von der Oberfläche!

Ich bin froh und glücklich das dieser Text funktioniert und viel zu sehr Anfänger um Deine Analyse zu bezweifeln. Und wie bekomme ich das nun schneller (zB. Eigenschaft .Text) und was meinst du mit unsicher?? Deine ganze Analyse -> Frage über Frage ?

stoxx 23. Mär 2010 15:58

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
@ Muetze1 .. nein, er schrieb ja, dass es ab der Stringgrid langsam wird, das zuweisen ist alles noch fix.

also das Problem ist, dass Du den gesamten Text in die Stringgrid kopierst. Das schafft die nicht wirklich. Dafür ist sie nicht gedacht.
Was Du brauchst ist eine "virtuelle" Stringgrid.
Du musst im Ereignis OnDrawCell den Text mit Canvas.Textout selbst zeichnen.
Und immer nur den bereich, der auf dem Bildschirm zu sehen ist. die Stringlist fungiert nur als Hintergrundspeicher.
Dann gehts auch fix ...
Für riesige Files, die größer sind als Dein Hauptspeicher, brauchst Du das File noch nichtmal in den Hauptspeicher laden.
Dann genügt es, wenn Du nur den aktuellen Bereich, der vom User gerade angezeigt werden möchte lädst und anzeigst.
Aber solche einfachen Dinge kann noch nicht mal Notepad .. Ultraedit macht das aber ...




Im Prinzip reicht für solche großen Textdateien dann auch eine TDrawGrid ...


P.S. für die Funktion StringReplace gibts in der JCL von Jedi eine schnellere Variante als die in der VCL

Franzelchen 23. Mär 2010 16:15

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Virtuelle Stringgrid?? langsam verstehe ich immer mehr Bahnhof.
StringReplace aus VCL --> Für das ersetzen von ca.200 ß(sz) in mehrere s sowie zurück ist die VCL doch noch schnell genug.

Sir Rufo 23. Mär 2010 16:20

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Er schreibt, dass das Befüllen des StringGrid sehr langsam ist ... und das glaube ich sogar :mrgreen:

1. StringGrid1.RowCount

Das ständige Erhöhen des Wertes stresst unnötig.
Setze am Anfang der Schleife den Wert und fertig

2. StringGrid1.Cells[ x, y ]

Benutze besser StringGrid1.Rows[ y ] und zwar so:
Delphi-Quellcode:
StringGrid1.Rows.BeginUpdate; // Anzeige der StringGrid.Reihen nicht mehr aktualisieren
for Zeile := 0 to StringGrid1.RowCount - 1 do
  begin
    Spalte := 1; // fängt bei 0 an, also ist es die 2. Spalte im StringGrid
    StringGrid1.Rows[ Zeile ][ Spalte ] := 'Tach auch';
  end;
StringGrid1.Rows.EndUpdate; // Anzeige der StringGrid.Reihen wieder aktualisieren
Denn sonst aktualisiert sich das Formular zu Tode

3. ProgressBar

Die ProgressBar braucht auch nicht jede Änderung mitzubekommen
Delphi-Quellcode:
MaxWert := 10000;
ProgressBar1.Max := MaxWert;
for i := 0 to MaxWert - 1 do
  begin
    if ( i mod 100 = 0 ) or ( i = MaxWert ) then
      ProgressBar1.Position := i;
  end;
Dann sollte das schon schneller laufen

stoxx 23. Mär 2010 16:24

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Franzelchen
Virtuelle Stringgrid?? langsam verstehe ich immer mehr Bahnhof.
StringReplace aus VCL --> Für das ersetzen von ca.200 ß(sz) in mehrere s sowie zurück ist die VCL doch noch schnell genug.

ich muss mich ein klein wenig berichtigen, Du musst gar nicht OnCellDraw nehmen.
Es geht auch so, wie Du es gemacht hast, dann aber mit einer zweiten Scrollbar neben der Stringgrid, welche diese ersetzt.
Stringgrid.rowcount wird auf 30 oder so gesetzt.

virtuell bedeutet. Du hast ein File mit 1 Mio Textzeilen.
Beim Anzeigen siehst Du aber nur vielleict 30 Zeilen in der Stringgrid.
Die Stringgrid hat nie mehr als 30 Zeilen effektive Einträge. Beim Scrollen wird Dir nur vorgegaugelt, es wäre soviel drin. in Wahrheit wird die gewünschte Anzeige erst dann live hineingemalt.
Du schmeißt also nicht 1 Mio Zeilen in die Stringgrid, sondern immer nur 30 ...

stoxx 23. Mär 2010 16:26

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Benutze besser StringGrid1.Rows[ y ] und zwar so:

.. ich hatte bei der Stringgrid gerade vergeblich BeginUpdate gesucht, .. in den Rows hat sich das also versteckt.

ja .. das wäre eine Maßnahme die sehr helfen könnte :mrgreen:

Sir Rufo 23. Mär 2010 16:28

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von stoxx
Du schmeißt also nicht 1 Mio Zeilen in die Stringgrid, sondern immer nur 30 ...

es ist ja etwas andres (und vor allem besser)

Die Komponente fragt diese 30 Zeilen per Index ab und ich muss nur darauf reagieren und diese Informationen liefern.
Aber auch nur genau in diesem Moment.

Franzelchen 23. Mär 2010 16:34

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von stoxx

ich muss mich ein klein wenig berichtigen, Du musst gar nicht OnCellDraw nehmen.
Es geht auch so, wie Du es gemacht hast, dann aber mit einer zweiten Scrollbar neben der Stringgrid, welche diese ersetzt.
Stringgrid.rowcount wird auf 30 oder so gesetzt.

virtuell bedeutet. Du hast ein File mit 1 Mio Textzeilen.
Beim Anzeigen siehst Du aber nur vielleict 30 Zeilen in der Stringgrid.
Die Stringgrid hat nie mehr als 30 Zeilen effektive Einträge. Beim Scrollen wird Dir nur vorgegaugelt, es wäre soviel drin. in Wahrheit wird die gewünschte Anzeige erst dann live hineingemalt.
Du schmeißt also nicht 1 Mio Zeilen in die Stringgrid, sondern immer nur 30 ...

Theoretisch verstehe ich das. aber praktisch gleich gar nicht.

@ Sir Rufo
Also zwischen beginUpdate und endUpdate den QuellText setzen und damit die Stringgrid Aktualisierung aufheben.

Ich werde das ganze mal ausprobieren.

Franzelchen 24. Mär 2010 13:31

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Sir Rufo
Er schreibt, dass das Befüllen des StringGrid sehr langsam ist ... und das glaube ich sogar :mrgreen:

1. StringGrid1.RowCount

Das ständige Erhöhen des Wertes stresst unnötig.
Setze am Anfang der Schleife den Wert und fertig

2. StringGrid1.Cells[ x, y ]

Benutze besser StringGrid1.Rows[ y ] und zwar so:
Delphi-Quellcode:
StringGrid1.Rows.BeginUpdate; // Anzeige der StringGrid.Reihen nicht mehr aktualisieren
for Zeile := 0 to StringGrid1.RowCount - 1 do
  begin
    Spalte := 1; // fängt bei 0 an, also ist es die 2. Spalte im StringGrid
    StringGrid1.Rows[ Zeile ][ Spalte ] := 'Tach auch';
  end;
StringGrid1.Rows.EndUpdate; // Anzeige der StringGrid.Reihen wieder aktualisieren
Denn sonst aktualisiert sich das Formular zu Tode

3. ProgressBar

Die ProgressBar braucht auch nicht jede Änderung mitzubekommen
Delphi-Quellcode:
MaxWert := 10000;
ProgressBar1.Max := MaxWert;
for i := 0 to MaxWert - 1 do
  begin
    if ( i mod 100 = 0 ) or ( i = MaxWert ) then
      ProgressBar1.Position := i;
  end;
Dann sollte das schon schneller laufen

So, jetzt hab ich's ausprobiert.
.beginUpdate sowie .endUpdate wird zwar von der Codevervollständigung unterstützt, der Compiler dagegen erwartet eine eckige Klammer und compiliert deshalb nicht.
Die Progressbar hab ich vorerst vollständig weggelassen so das mein Text jetzt so aussieht:

Delphi-Quellcode:
begin
Screen.Cursor := crHourGlass;
startZeit := now;
  x:=tstringlist.Create;
  x.LoadFromFile('C:\DB\DatenTest.tmp');

  x.Text:= StringReplace(x.Text,'ß','SSSSSSS', [rfReplaceAll]);
  x.Sort;
  x.Text:= StringReplace(x.Text,'SSSSSSS','ß',[rfReplaceAll]);

  x.SaveToFile('sortiert.txt');


// ab hier wird es extrem langsam

  a:=0;
 
// stringgrid1.rows.beginupdate;  //fehlermeldung: [ erwartet
//   try
  for b:=0 to x.count-1 do
  begin
      if b>0 then begin
       if x.strings[b]=x.Strings[b-1] then begin
          StringGrid1.cells[1,a]:= inttostr(strtoint (StringGrid1.cells[1,a])+1)
      end else begin
               inc(a);
               StringGrid1.cells[1,a] := '1';
               StringGrid1.cells[0,a] := x.strings[b];
               StringGrid1.RowCount := StringGrid1.RowCount+1;
               end;
      end else begin
               StringGrid1.cells[0,a]:=x.Strings[b];
               StringGrid1.cells[1,a]:='1';
      end;
   end;
//   finally;
//  stringgrid1.rows.endUpdate //fehlermeldung: [ erwartet
x.Destroy;
StopZeit := Now;
StatusBar6.Panels[1].Text :='SuchZeit : '+ FormatDateTime('nn:ss:zzz', StopZeit - StartZeit) ;
Screen.Cursor := crDefault;
end;
Try finally hab ich jetzt nur reingesetzt, sicher bin ich mir nicht wozu das gut sein soll.

Sir Rufo 24. Mär 2010 14:01

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Dann versuch es mal so:
Delphi-Quellcode:
begin
  Screen.Cursor := crHourGlass;
  startZeit := now;
  x := tstringlist.Create;
  x.LoadFromFile( 'C:\DB\DatenTest.tmp' );

  x.Text := StringReplace( x.Text, 'ß', 'SSSSSSS', [ rfReplaceAll ] );
  x.Sort;
  x.Text := StringReplace( x.Text, 'SSSSSSS', 'ß', [ rfReplaceAll ] );

  x.SaveToFile( 'sortiert.txt' );


  // ab hier wird es extrem langsam

  a := 0;
  // StringGrid auf die maximal mögliche Zeilenanzahl setzen
  stringgrid1.RowCount := x.Count;

  for b := 0 to x.Count - 1 do
    begin
      stringgrid1.Row[ a ].BeginUpdate;
      try

        if b > 0 then
          begin
            if x.strings[ b ] = x.strings[ b - 1 ] then
              begin
                stringgrid1.cells[ 1, a ] := inttostr( strtoint( stringgrid1.cells[ 1, a ] ) + 1 )
              end
            else
              begin
                inc( a );
                stringgrid1.cells[ 1, a ] := '1';
                stringgrid1.cells[ 0, a ] := x.strings[ b ];
              end;
          end
        else
          begin
            stringgrid1.cells[ 0, a ] := x.strings[ b ];
            stringgrid1.cells[ 1, a ] := '1';
          end;

      finally
        stringgrid1.Row[ a ].EndUpdate;
      end;
    end;
  // Jetzt setzen wir die korrekte Anzahl der Zeilen
  stringgrid1.RowCount := a;

  x.Destroy;
  StopZeit := now;
  StatusBar6.Panels[ 1 ].Text := 'SuchZeit : ' + FormatDateTime( 'nn:ss:zzz', StopZeit - startZeit );
  Screen.Cursor := crDefault;
end;

p80286 24. Mär 2010 16:57

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
warum zählst Du eigentlich die doppelten Einträge nicht schon vorher und schreibst erst zunm Schluß das Ergebnis in das Stringgrid?

Hab ich's überlesen oder hat bisher noch keiner darauf hingewiesen?
Trenn die Daten von der Oberfläche, und ein Stringgrid ist Oberfläche.

Gruß
K-H

DeddyH 24. Mär 2010 17:08

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Wenn wir schon beim Meckern sind:
Delphi-Quellcode:
x := TStringList.Create; //wobei ich die nicht unbedingt x nennen würde
try
  //ganz viel Code
finally
  x.Free; //nicht Destroy
end;

Muetze1 24. Mär 2010 17:36

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von p80286
Hab ich's überlesen oder hat bisher noch keiner darauf hingewiesen?
Trenn die Daten von der Oberfläche, und ein Stringgrid ist Oberfläche.

Zitat:

Zitat von Muetze1
Grundlegend: Trenne Daten von der Oberfläche!

Zitat:

Zitat von DeddyH
Wenn wir schon beim Meckern sind: ...

Zitat:

Zitat von Muetze1
2. try/finally fehlt komplett

Auch alle anderen Punkte wurden schon genannt...

Franzelchen 25. Mär 2010 13:23

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Muetze1
Zitat:

Zitat von p80286
Hab ich's überlesen oder hat bisher noch keiner darauf hingewiesen?
Trenn die Daten von der Oberfläche, und ein Stringgrid ist Oberfläche.

Zitat:

Zitat von Muetze1
Grundlegend: Trenne Daten von der Oberfläche!

Zitat:

Zitat von DeddyH
Wenn wir schon beim Meckern sind: ...

Zitat:

Zitat von Muetze1
2. try/finally fehlt komplett

Auch alle anderen Punkte wurden schon genannt...


try/finally ist erledigt, mit Progreßbar von 17 sec auf 12 sec Laufzeit verringert, ohne Progressbar auf 2,5 bis 3 sec.

x. Stringlist in SL. umbenannt ist erledigt,

Grundlegend: Trenne Daten von der Oberfläche. --> derzeitiges Problem.

Was heißt Daten von der Oberfläche trennen? Eine zweite Stringlist (zweifeldrig) für die Ergebnisse und anschließend Stringlist in Stringgrid laden??

Gruß eines total verwirrten Anfängers

PS. Ihr habt mich heiß gemacht, jetzt erklärt mir worum es geht.

Sir Rufo 25. Mär 2010 15:46

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Die Trennung erreicht man, wenn man sich an das EVA-Prinzip hält:

E - Eingabe
V - Verarbeitung
A - Ausgabe

Beispiel für EVA:

E - Benutzer wählt einen Dateinamen aus (z.B. in einem TEdit)

V - Datei wird geöffnet und die Daten ausgelesen (z.B. in eine TStringList)
V - Die Daten werden verarbeitet (Ergebnis z.B. in eine TStringList)

A - Ausgabe der berechneten Daten (z.B. in ein TStringGrid)

Der Quelltext deines Formulars braucht also nur noch eine Behandlung für die Eingabe (hier des Dateinames)
und für die Ausgabe der Ergebnis-TStringList in TStringGrid

Die Verarbeitung selber kann man in einer separaten Unit auslagern.

Dadurch gewinnt man nicht nur Geschwindigkeit bei der Ausführung der Anwendung,
sondern auch bei der Entwicklung, da die einzelnen Units nun nicht mehr so vollgestopft sind.

Um bei diesem Beispiel zu bleiben, würde folgendes in der Verarbeitungs-Unit stehen:
Delphi-Quellcode:
unit uVerarbeitung;

interface

function VerabeiteDatenAusDatei( const FileName : string; const Ergebnis : TStringList ) : boolean;

implementation

function VerabeiteDatenAusDatei( const FileName : string; const Ergebnis : TStringList ) : boolean;
var
  sl : TStringList;
begin
  // Erstmal ist das Ergebnis noch nicht in Ordnung
  Result := False;

  if FileExists( FileName ) then
    begin
      sl := TStringList.Create;
      try
        sl.LoadFromFile( FileName );
        // Jetzt machen wir was ganz Tolles mit den Daten und schreiben das in die TStringList Ergebnis
        Ergebnis.Add( sl[ 0 ] );
        // Ist alles korrekt durchlaufen und sind die Ergebnisse so korrekt dann
        Result := True;
      finally
        sl.Free;
      end;
    end;
end;

end.
In der Form wird das dann so aufgerufen:
Delphi-Quellcode:
uses uVerarbeitung;

procedure TForm1.HierPassiertEsJetzt;
  var
    MeinErgebnis : TStringList;
  begin
    MeinErgebnis := TStringList.Create;
    try
      if VerabeiteDatenAusDatei( Edit1.Text, MeinErgebnis ) then
        begin
          // Hier kommt der Quelltext für das Befüllen des StringGrids aus MeinErgebnis
        end;
    finally
      MeinErgebnis.Free;
    end;
  end;

Franzelchen 26. Mär 2010 14:27

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Hallo,
Das mit dem Trennen das auftrennen in ButtonClick und Funktion gemeint ist, ist mir dann heute Morgen eingefallen.

Anbei mein noch ziemlich unreifer erster Versuch:

Delphi-Quellcode:
function Testfunktion(SL:TStringlist):Tstrings;
var a,b :integer;
   SList : TStringlist;
   SG: TStringgrid;
begin
  a := 0;
  // StringGrid auf die maximal mögliche Zeilenanzahl setzen
  SG.RowCount := SList.Count;
  for b := 0 to SList.Count - 1 do
    begin
      SG.Rows[ a ].BeginUpdate;
      try
        if b > 0 then
          begin
            if SList.strings[ b ] = SList.strings[ b - 1 ] then
              begin
                SG.cells[ 1, a ] := inttostr( strtoint( SG.cells[ 1, a ] ) + 1 )
              end
            else
              begin
                inc( a );
                SG.cells[ 1, a ] := '1';
                SG.cells[ 0, a ] := SList.strings[ b ];
              end;
          end
        else
          begin
            SG.cells[ 0, a ] := SL.strings[ b ];
            SG.cells[ 1, a ] := '1';
          end;

      finally
        SG.Rows[ a ].EndUpdate;
      end;
    end;
  // Jetzt setzen wir die korrekte Anzahl der Zeilen
  SG.RowCount := a;
  Result := SG.Rows[a];
end;

procedure TForm1.Button2Click(Sender: TObject);
var
startzeit,stopzeit:TDateTime;
SL : TStringlist;
begin
  Screen.Cursor := crHourGlass;
  startZeit := now;
  SL := TStringlist.Create;
  SL.LoadFromFile( 'DatenTest.tmp' );

  SL.Text := StringReplace( SL.Text, 'ß', 'SSSSSSS', [ rfReplaceAll ] );
  SL.Sort;
  SL.Text := StringReplace( SL.Text, 'SSSSSSS', 'ß', [ rfReplaceAll ] );

  SL.SaveToFile( 'sortiert.txt' );

  Testfunktion(SL) ;

  SL.Free;
  StopZeit := now;
  Label1.Caption := FormatDateTime( 'nn:ss:zzz', StopZeit - startZeit );
  Screen.Cursor := crDefault;
end;
Es gibt einen Zugriffsfehler innerhalb der Funktion aber warum?

Sir Rufo 26. Mär 2010 14:47

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Ich weiß ja nicht was du damit erreichen willst ... ist irgendwie ohne hand und fuß

Der Zugriffsfehler kommt daher, dass du die Variable SG nicht instanziert hast.
Delphi-Quellcode:
SG := TStringGrid.Create( nil );
Aber wie gesagt, das ist mehr als komisch, was du da machst.

Franzelchen 26. Mär 2010 16:26

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Sir Rufo
Ich weiß ja nicht was du damit erreichen willst ... ist irgendwie ohne hand und fuß

Der Zugriffsfehler kommt daher, dass du die Variable SG nicht instanziert hast.
Delphi-Quellcode:
SG := TStringGrid.Create( nil );
Aber wie gesagt, das ist mehr als komisch, was du da machst.

Wieso ist das komisch? Die Prozedur erzeugt eine Stringliste. Die Stringliste wird an die Funktion übergeben und danach gelöscht. Die Funktion, ja die hat im Moment keinen Rückgabewert ,
Delphi-Quellcode:
  SL.SaveToFile( 'sortiert.txt' );

Rückgabewert := Testfunktion(SL) ;

  SL.Free;
weil ich Schwierigkeiten mit der Zuweisung habe. Stringgrid.cells hat String, Stringgrid.Rows dagegen TString.
Ich muß leider sagen, dies ist meine allererste Funktion und soweit wie ich weiß soll eine Funktion wiederverwendbar sein.

p80286 26. Mär 2010 16:49

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Hallo Franzelchen,

wie wär es denn wenn Du uns zunächst mal sagst was Du eigentlich erreichen willst?
Für mich sieht das so aus, als würdest Du irgendeine Textdatei einlesen, sortieren und in einem Stringgrid ausgeben. (Das savetofile ignorier ich jetzt)
Dann markierst Du doppelte Datensätze im Stringgrid mit Zahlen >1 .

Ist das soweit richtig, ist es auch das was Du erreichen willst?

Edith:
(Das mit Funktionen und Prozeduren lassen wir zunächst auch einmal)

Gruß
K-H

Sir Rufo 26. Mär 2010 17:17

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Franzelchen
Zitat:

Zitat von Sir Rufo
Ich weiß ja nicht was du damit erreichen willst ... ist irgendwie ohne hand und fuß

Der Zugriffsfehler kommt daher, dass du die Variable SG nicht instanziert hast.
Delphi-Quellcode:
SG := TStringGrid.Create( nil );
Aber wie gesagt, das ist mehr als komisch, was du da machst.

Wieso ist das komisch? Die Prozedur erzeugt eine Stringliste. Die Stringliste wird an die Funktion übergeben und danach gelöscht. Die Funktion, ja die hat im Moment keinen Rückgabewert ,
Delphi-Quellcode:
  SL.SaveToFile( 'sortiert.txt' );

Rückgabewert := Testfunktion(SL) ;

  SL.Free;
weil ich Schwierigkeiten mit der Zuweisung habe. Stringgrid.cells hat String, Stringgrid.Rows dagegen TString.
Ich muß leider sagen, dies ist meine allererste Funktion und soweit wie ich weiß soll eine Funktion wiederverwendbar sein.

Aber mit deiner Vorgehensweise baust du dir gerade eine riesige Datenmüllhalde.
In deiner Funktion musst du TStringGrid erzeugen (SG).
Als Rückgabewert gibst du einen Teil von genau diesem SG zurück.
Aber du darfst das Objekt SG in der Funktion nicht löschen, weil sonst auch der Rückgabewert verschwindet.
Als Fazit bleibt, SG wird niemals freigegeben, niemals mehr benutzt und bleibt somit im Speicher bis das Programm beendet wird.

Ohne die Funktion (was da überhaupt passieren soll) ist das schon mal grundverkehrt.

In meinem Beispiel habe ich Dir gezeigt wie das vom Prinzip her geht.

Erzeuge eine Instanz (TStringList) und übergebe der Funktion diese Instanz, auf das die Funktion dort die Ergebnisse reinschreiben kann.

Somit hast du dort, wo du dann diese Daten weiterverarbeitest (zur Anzeige) auch die Kontrolle darüber, wann diese Instanz wieder aus dem Speicher entfernt werden kann (z.B. nach der Anzeige).

Eine visuelle Komponente (TStringGrid) zum Berechnen zu benutzen ist schon vom Ansatz falsch, da diese Komponenten zum Anzeigen gut geeignet sind aber auch nur dafür.

Franzelchen 26. Mär 2010 19:58

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von p80286
Hallo Franzelchen,

wie wär es denn wenn Du uns zunächst mal sagst was Du eigentlich erreichen willst?
Für mich sieht das so aus, als würdest Du irgendeine Textdatei einlesen, sortieren und in einem Stringgrid ausgeben. (Das savetofile ignorier ich jetzt)
Dann markierst Du doppelte Datensätze im Stringgrid mit Zahlen >1 .

Ist das soweit richtig, ist es auch das was Du erreichen willst?

Edith:
(Das mit Funktionen und Prozeduren lassen wir zunächst auch einmal)

Gruß
K-H

Hallo K-H,
Deine Analyse ist völlig richtig. Mein Ziel ist es die ziemlich langsam ablaufende Prozedur (siehe Beitrag 21) möglichst zu beschleunigen. Wenn das nicht über die reine ButtonClick geht, dann vielleicht über eine Funktion (Trenne Daten von Oberfläche!).
Gruß

Sir Rufo 26. Mär 2010 20:03

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Zitat:

Zitat von Franzelchen
Wenn das nicht über die reine ButtonClick geht, dann vielleicht über eine Funktion (Trenne Daten von Oberfläche!).
Gruß

ButtonClick ist doch nur ein Event (ein Ereignis) wo dann etwas passieren soll, sonst nix.

Durch dieses Ereignis kann alles passieren (z.B. eine Berechnung und die Ausgabe der Berechnung).

Allerdings sollte die Berechnung ohne visuelle Komponenten auskommen.
Erst bei der Ausgabe (nach der Berechnung) kommen die visuellen Komponenten ins Spiel.

Dies versuchen wir dir seit einigen Beiträgen schon zu vermitteln, aber du scheinst da etwas beratungsresistent zu sein :mrgreen:

Franzelchen 26. Mär 2010 20:23

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
@ Sir Rufo

Dein letzter Beitrag hat mich überzeugt.
Zitat:

Zitat von Sir Rufo
Ohne die Funktion (was da überhaupt passieren soll) ist das schon mal grundverkehrt. ?????

In meinem Beispiel habe ich Dir gezeigt wie das vom Prinzip her geht.

Erzeuge eine Instanz (TStringList) und übergebe der Funktion diese Instanz, auf das die Funktion dort die Ergebnisse reinschreiben kann.

Somit hast du dort, wo du dann diese Daten weiterverarbeitest (zur Anzeige) auch die Kontrolle darüber, wann diese Instanz wieder aus dem Speicher entfernt werden kann (z.B. nach der Anzeige).

Eine visuelle Komponente (TStringGrid) zum Berechnen zu benutzen ist schon vom Ansatz falsch,(??????) da diese Komponenten zum Anzeigen gut geeignet sind aber auch nur dafür.

Die Fragezeichen zeigen vermutlich worin ich jetzt schon meine Probleme sehe.

Delphi-Quellcode:
function VerabeiteDatenAusDatei( const FileName : string; const Ergebnis : TStringList ) : boolean;
Ich begreife nicht wieso Du an die Funktion eine Stringliste übergibst

Delphi-Quellcode:
      if VerabeiteDatenAusDatei( Edit1.Text, MeinErgebnis ) then
und diese als Ergebnis noch vorhanden ist, wenn doch der einzigste Rückgabewert der Funktion vom Typ boolean ist?

Franzelchen 26. Mär 2010 20:27

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
@ Sir Rufo

Dein letzter Beitrag hat mich überzeugt.
Zitat:

Zitat von Sir Rufo
Ohne die Funktion (was da überhaupt passieren soll) ist das schon mal grundverkehrt. ?????

In meinem Beispiel habe ich Dir gezeigt wie das vom Prinzip her geht.

Erzeuge eine Instanz (TStringList) und übergebe der Funktion diese Instanz, auf das die Funktion dort die Ergebnisse reinschreiben kann.

Somit hast du dort, wo du dann diese Daten weiterverarbeitest (zur Anzeige) auch die Kontrolle darüber, wann diese Instanz wieder aus dem Speicher entfernt werden kann (z.B. nach der Anzeige).

Eine visuelle Komponente (TStringGrid) zum Berechnen zu benutzen ist schon vom Ansatz falsch,(??????) da diese Komponenten zum Anzeigen gut geeignet sind aber auch nur dafür.

Die Fragezeichen zeigen vermutlich worin ich jetzt schon meine Probleme sehe.

Delphi-Quellcode:
function VerabeiteDatenAusDatei( const FileName : string; const Ergebnis : TStringList ) : boolean;
Ich begreife nicht wieso Du an die Funktion eine Stringliste übergibst

Delphi-Quellcode:
      if VerabeiteDatenAusDatei( Edit1.Text, MeinErgebnis ) then
und diese als Ergebnis noch vorhanden ist, wenn doch der einzigste Rückgabewert der Funktion vom Typ boolean ist

nicht beratungsresistent eher Anfänger, sowas gibt es auch.

Sir Rufo 26. Mär 2010 20:37

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Ich übergebe der Funktion eine Instanz einer TStringList - jepp

In diese TStringList legt die Funktion das Ergebnis ab.

Der Rückgabewert true oder false ist nur dafür da, ob die Funktion z.B. korrekt durchgelaufen ist.
Delphi-Quellcode:
function GibMirWerteInDieListe( const Liste : TStringList ) : boolean;
begin
  Liste.Add( 'Dies wurde in der Funktion hinzugefügt!' );
  Result := True;
end;
Delphi-Quellcode:
procedure IchRufeDieFunktionAuf;
var
  EineListe : TStringList;
begin
  EineListe := TStringList.Create;
  try
   
    if GibMirWerteInDieListe( EineListe ) then
      ShowMessage( EineListe.Text );
 
  finally
    EineListe.Free;
  end;
end;
Wenn du das ausführst, dann bekommst du eine Meldung mit 'Dies wurde in der Funktion hinzugefügt!'.

Ich hoffe es wird jetzt klarer.

Franzelchen 10. Apr 2010 13:46

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Ok, nach der Neuinstallation meines Rechners hab ich eine Lösung:
Delphi-Quellcode:
function VerabeiteDatenAusDatei( const FileName : string; const Ergebnis : TStringList ) : boolean;
var
  sL : TStringList;
  i,Zahl: integer;
begin
  // Erstmal ist das Ergebnis noch nicht in Ordnung
  Result := False;

  if FileExists( FileName ) then
    begin
      sL := TStringList.Create;
      try
        sL.LoadFromFile( FileName );
        // Jetzt machen wir was ganz Tolles mit den Daten und schreiben das in die TStringList Ergebnis
//        sL.Text:= StringReplace(sL.Text,'ß','SSSSSSS', [rfReplaceAll]);
//        sL.Sort;
//        sL.Text:= StringReplace(sL.Text,'SSSSSSS','ß',[rfReplaceAll]);
//        sL.SaveToFile('sortiert.txt');
          Zahl := 1;
          for i:=0 to sL.count-1 do
          begin
            if i>0 then
             begin
             if sl.Strings[i]<>sL.Strings[i-1] then
              begin
              Zahl := 1;
              end;

             if sL.strings[i]=sL.Strings[i-1] then
              begin
              Zahl := Zahl+1;
              end;
             end;

             Ergebnis.Add(sl.Strings[i]+#9+IntToStr(Zahl)) ;

          end;

   //     Ergebnis.Add( sl[ 0 ] );
        // Ist alles korrekt durchlaufen und sind die Ergebnisse so korrekt dann
        Result := True;
      finally
        sL.Free;
      end;
    end;
end;
Das Ergebnis dieser Funktion ist zB.

NameA ---> 1
NameA ---> 2
NameA ---> 3
NameB ---> 1
NameB ---> 2 usw.

Ziel der Funktion

NameA ---> 3
NameB ---> 2 usw.

Irgendwie muß ich bei dem Vergleich if sl[i] = sl[i-1] etwas einfügen welches mehrere i einliest und zählt. Anschließend den maximalen Zahlenwert ausgibt der dann mit einem sl[i] in die Ergebnisstringliste geschrieben wird.

Ich habe auch andere Funktionen und Prozeduren aus DP versucht, aber keine wirklich schnellen gefunden.

Ich hoffe auf Eure weitere Unterstützung.

Franzelchen 11. Apr 2010 13:09

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Schade das hier niemand weiterhelfen kann!

alzaimar 11. Apr 2010 16:23

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Was soll die Funktion denn machen? Die einzelnen Strings zählen?
Dann mach das doch:
Code:
Für jede Zeile S in der StringListe:
  Inc (Zähler [S]);
Als Zähler verwendest Du eine TStringlist. Jedem String in der Stringlist kann ein 'Object' zugeordnet werden. Man kann nun dieses Object einfach als Zähler verwenden:

Delphi-Quellcode:
i := ZaehlerListe.IndexOf(ZuZaehlenderString);           // Finde Eintrag in der Zaehlerliste
If i=-1 then                                               // Es existiert noch kein Eintrag,
  ZaehlerListe.AddObject(ZuZaehlenderString, TObject(1)) // erstelle also einen mit dem Wert 1
else begin
  n := Integer (ZaehlerListe.Objects[i]);             // Ansonsten schnapp dir den Zähler und
  ZaehlerListe.Objects[i] := TObject(n+1);                                 // erhöhe ihn um 1.
end;
Wenn Du fertig mit Zählen bist, geh die Zaehlerliste durch und erzeuge deine Ergebnisliste.

[edit]Schusseligkeitsfehler korrigiert, die Hawkeye219 entdeckt hat. [/edit]

Hawkeye219 11. Apr 2010 18:23

Re: TStringlist, THashedStringlist gibts nichts schnelleres?
 
Hey alzaimar,

"IndexOf" und "0" => "-1", sonst passen die Kommentare nicht zu den Anweisungen ;-)

Gruß Hawkeye


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:03 Uhr.
Seite 1 von 2  1 2      

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