![]() |
Suche effizienter machen
Hallo,
mein Programm soll für voreingestellte Schlüsselwörter, wenn etwas gesucht oder die Datei geöffnet wurde, farbig hervorheben. Das funktioniert auch. Mein Problem ist nur, wenn ich sehr große Dateien habe ala Zeilen >2000, dann dauert das eine halbe Ewigkeit. Ich wollte nur mal wissen ob wer eine Idee hat, dieses Suchen/markieren effizienter zu machen oder ob ich mit der Geschwindigkeit leben muss. Hier der Code:
Delphi-Quellcode:
wobei FSelect eine Stringlist ist
i2:=0;
for ii := 0 to FSelectCount-1 do begin if FSelect.Strings[ii] <>'' then begin if (text<>'') OR (text2<>'') OR (text3<>'') then begin if (Pos( LowerCase(text), LowerCase( FSelect.Strings[ii] ) )) > 0 then begin i:=Pos( LowerCase(text), LowerCase( FSelect.Strings[ii] ) ); mmoLines.SelStart := i+i2-1; mmoLines.SelLength := Length(text); mmoLines.SelAttributes.Color := c; mmoLInes.SelAttributes.Style := [fsBold]; mmoLines.SelLength := 0; end; if Pos( LowerCase(text2), LowerCase( FSelect.Strings[ii] ) ) > 0 then begin i:=Pos( LowerCase(text2), LowerCase( FSelect.Strings[ii] ) ); mmoLines.SelStart := i+i2-1; mmoLines.SelLength := Length(text2); mmoLines.SelAttributes.Color := c2; mmoLInes.SelAttributes.Style := [fsBold]; mmoLines.SelLength := 0; end; if Pos( LowerCase(text3), LowerCase( FSelect.Strings[ii] ) ) > 0 then begin i:=Pos( LowerCase(text3), LowerCase( FSelect.Strings[ii] ) ); mmoLines.SelStart := i+i2-1; mmoLines.SelLength := Length(text3); mmoLines.SelAttributes.Color := c3; mmoLInes.SelAttributes.Style := [fsBold]; mmoLines.SelLength := 0; end; end; end; i2 := i2+Length(FSelect.Strings[ii])+2; end; und text und color und c aus einer ini datei gelesen werden über Ideen wäre ich dankbar :) |
Re: Suche effektiver machen
Moin, Moin,
Spontan drei Bemerkungen dazu: 1) Das ständige "LowerCase(FSelect.Strings[ii])" kostet Zeit und würde überflüssig, wenn es 1x VOR der Schleife erledigt wird. 2) Prüfe, ob die Suche nach einem Schlüsselwort in der Stringlliste mit IndexOf() schneller ist als mit Pos() 3) Wenn dein Code seinen Zweck erfüllt, ist er bereits effektiv! Wenn er seinen Zweck erfüllen und besonders schnell sein soll, dann ist er effizient! |
Re: Suche effektiver machen
Hallo,
mal so ein bisserl schmutzig von mir dahingeschrieben:
Delphi-Quellcode:
Mach Dir dafür 'nen boolschen Schalter, dann musst Du nur einmal abfragen
if (text<>'') OR (text2<>'') OR (text3<>'') then
Delphi-Quellcode:
Das kannst Du schon vor Deiner For-Schleife machen, ist b = false, kannst Du Dir die For-Schleife direkt sparen.
b := (text<>'') OR (text2<>'') OR (text3<>'');
Text... werden bei jeder Abfrage mit Lowercase behandelt, mache das einmal vor der Schleife.
Delphi-Quellcode:
Prüfe bitte, ob Du vorab auch FSelect.Strings[ii] in Lowercase wandeln kannst, dann mach das vorab in einer separaten Schleife.
if Pos( LowerCase(text3), LowerCase( FSelect.Strings[ii] ) ) > 0 then
begin i:=Pos( LowerCase(text3), LowerCase( FSelect.Strings[ii] ) ); Die Position wird hier zweimal ermittelt, eventuell machst Du das besser so:
Delphi-Quellcode:
@taaktaak, IndexOf ist hier nicht geeignet, da nicht nach Strings in der Liste gesucht wird, sondern nach Teilstrings in den einzelnen Listeneinträgen, das kann IndexOf meines Wissens nicht.
i := Pos( LowerCase(text3), LowerCase( FSelect.Strings[ii] ) );
if i > 0 then begin Stephan PS: taaktaak war schneller als ich :x |
Re: Suche effektiver machen
Hallo,
wenn du die Einfärbung nur brauchst um sie auf dem Bildschirm darzustellen dann ist es effizienter wenn du nur die Zeilen bearbeitest, die momentan sichtbar sind. Dafür gibt es mit der SynEdit auch schon fertige Komponenten. mfg DerDan |
Re: Suche effizienter machen
danke schon mal für die Antworten :thumb:
Nur was ich nicht ganz verstehe ist das ich das LowerCase vor der Schleife machen soll. Sann kennt er doch gar nicht "ii"?! und wenn ich das wieder in einer Schleife mache, hab ich ja auch nichts mit gewonnen o_O Sorry, bin Anfänger ^^' |
Re: Suche effizienter machen
Mir ist nicht klar, wie du die Schlüsselwörter bereitstellst.
Lege eine Stringlist an, in der jedes Schlüsselwort ein Listenelement ist und dort als LowerCase abgelegt ist. Dann kannst du auch mit IndexOf() arbeiten. |
Re: Suche effizienter machen
Die Schlüsselwörter speicher ich vorher in eine IniDatei
und lese sie dann an der Stelle wieder aus
Delphi-Quellcode:
jetzt nur mal für den ersten text
ini :=TIniFile.Create(ExtractFilePath(ParamStr(0))+'settings.ini');
text := ini.ReadString('settings','text1','Error'); color := ini.ReadString('settings','color1','clred'); if color<>'' then begin c:=StringToColor(color); end; |
Re: Suche effizienter machen
Hallo,
Zitat:
Für jeden Eintrag in FSelect.Strings werden text, text2 und text3 in Lowercase gesetzt. Das kannst Du vor der Schleife machen, diese Werte sind unabhängig vom Inhalt der Strings. Wenn Du ohne Probleme FSelect.Strings in Kleinbuchstaben umwandeln kannst, weil es ausserhalb der Schleife z. B. nicht gebraucht wird, dann mach' eine zweite Schleife vor die jetzige Schleife.
Delphi-Quellcode:
dann wird aus
for ii := 0 to FSelect.count - 1 ) do FSelect.Strings[ii] := lowercase(FSelect.Strings[ii]);
Delphi-Quellcode:
if Pos( LowerCase(text3), LowerCase( FSelect.Strings[ii] ) ) > 0 then
begin i:=Pos( LowerCase(text3), LowerCase( FSelect.Strings[ii] ) );
Delphi-Quellcode:
und wenn Du das dann noch vertauschst, wird daraus
if Pos(text3,FSelect.Strings[ii]) > 0 then
begin i:=Pos(text3,FSelect.Strings[ii]);
Delphi-Quellcode:
Dadurch sparst Du Dir sehr viele Lowercase und sehr viele Pos.
i:=Pos(text3,FSelect.Strings[ii]);
if i > 0 then begin Stephan |
Re: Suche effizienter machen
ah, ok jetzt hab ich das verstanden.
Danke Nur ob ich die Strings[ii] in einer seperaten schleife klein mache oder in der "richtigen" ist doch eigentlich egal?! :gruebel: Und wie könnt ich jetzt mal am besten testen (in Zeitwerten) wie effizienter das ganze geworden ist? So rein nach Gefühl ist das denke schon bisschen schneller, aber würde mich mal interessieren wie viel das nun genau gebracht hat. Muss ich dafür jetzt testweise kompletten Timer programmieren? |
Re: Suche effizienter machen
Hallo,
Zitat:
Wenn die Liste also 1000 Einträge enthält, wird jeder Eintrag der Stringliste 1 mal kleingemacht. In Deiner Variante wird jeder Eintrag der Stringliste 1000 mal drei mal kleingemacht. Das läppert sich zusammen, auch wenn einmal kleinmachen allein gaaaanz schnell geht :wink: Was das bringt: Nimm Deine "alte" Fassung mit einer definierten Liste und definiertem Text und schau auf die Uhr, wielange das dauert. Dann überarbeitest Du das Programm und machst den gleichen Test nochmal. Die Uhr kannst Du Dir mit Delphi "selber bauen". Vorher:
Delphi-Quellcode:
Uhrzeit aufschreiben
ShowMessage(DateTimeToStr(Now));
Nachher:
Delphi-Quellcode:
Uhrzeit aufschreiben und Zeitdifferenz ausrechnen.
ShowMessage(DateTimeToStr(Now));
Stephan |
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:37 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