AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi [Konzeptfrage] ist Listbox schneller zu durchsuchen?
Thema durchsuchen
Ansicht
Themen-Optionen

[Konzeptfrage] ist Listbox schneller zu durchsuchen?

Ein Thema von juergen · begonnen am 24. Sep 2008 · letzter Beitrag vom 26. Sep 2008
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.174 Beiträge
 
Delphi 11 Alexandria
 
#1

[Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 24. Sep 2008, 22:14
Hallo zusammen,

ich durchsuche per for-Schleife eine Listbox..
Ich muss eine Scheife nehmen, weil ich per Enter immer weiter suchen lasse.
Suchtext eingeben -> Enter -> 1. Ergebnis
Enter -> 2. Ergebnis wird angezeigt usw.

Das funktioniert soweit, dauert allerdinngs bei ca. 8000 Einträgen auch schon bis zu 13 Sekunden...
Meine Kernkomponenten innerhalb der Schleife sind:
Delphi-Quellcode:
type
  TSuche = record
    Text: AnsiString;
    ItemPos: integer;
    StrPos: integer;
  end;
//...

var
  i, NextPos: Integer;
  ItemText: AnsiString;
begin
  if Suche.ItemPos = -1 then
    Suche.ItemPos := 0;
  Suche.Text := AnsiUpperCase(Edit1.Text); // Edit1 = Suchtext

  for i := Suche.ItemPos to Pred(Search_Form.Listbox.Count) do
  begin
    ItemText := AnsiUpperCase(Search_Form.Listbox.Items.Strings[i]);
    if Suche.StrPos > 0 then
    begin
      NextPos := pos(Suche.Text, Copy(ItemText, Suche.StrPos +
        length(Suche.Text), length(ItemText) - Suche.StrPos));
      if NextPos > 0 then
        Suche.StrPos := Suche.StrPos + length(Suche.Text) + NextPos - 1
      else
        Suche.StrPos := 0;
    end
    else
      Suche.StrPos := pos(Suche.Text, ItemText);
....
Ich hatte schon einiges optimiert (ursprünglich 21 Sek), bin nun aber zu obigen Ergebnis gelangt und habe damit das für mich Machbare erreicht.

Besteht hier überhaupt noch eine Chance das Ganze wesentlich zu beschleunigen?
Verbesserungen um einzelne Prozentpünktchen sind zwar generell auch interessant, aber so richtig interesant wäre alles was mehr wie 15% bringen würde.
Gibt es vllt. eine ganz andere Vorgehensweise?

Ich hatte schon die Idee alles in eine Textdatei zu speichern und diese dann zu durchsuchen.
Das würde sehr schnell gehen, aber wie suche ich dann jeweils weiter ohne eine Schleife?


Danke schon mal vorab!
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
grenzgaenger
(Gast)

n/a Beiträge
 
#2

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 24. Sep 2008, 22:17
schon mal an .beginupdate und .endupdate gedacht
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#3

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 24. Sep 2008, 22:28
Und alles, was du aus GUI-Komponenten holst, zwischenspeichern! Das heißt in diesem Fall den Text des Edits und die Strings der Listbox. Zum Beginn der Suche in eine passend gescopete Variable kopieren und nur bei Änderung updaten.
Lukas Erlacher
Suche Grafiktablett. Spenden/Gebrauchtangebote willkommen.
Gotteskrieger gesucht!
For it is the chief characteristic of the religion of science that it works. - Isaac Asimov, Foundation I, Buch 1
  Mit Zitat antworten Zitat
Benutzerbild von juergen
juergen

Registriert seit: 10. Jan 2005
Ort: Bönen
1.174 Beiträge
 
Delphi 11 Alexandria
 
#4

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 24. Sep 2008, 22:43
Hallo,
Zitat von DGL-luke:
Und alles, was du aus GUI-Komponenten holst, zwischenspeichern! Das heißt in diesem Fall den Text des Edits und die Strings der Listbox. Zum Beginn der Suche in eine passend gescopete Variable kopieren und nur bei Änderung updaten.
Da ich in der Listbox nichts ändere sondern nur einen String suche, bringt das doch nichts, oder?
Hab's auch gerade getestet, kein Unterschied.


Zitat von DGL-luke:
Und alles, was du aus GUI-Komponenten holst, zwischenspeichern! Das heißt in diesem Fall den Text des Edits und die Strings der Listbox. Zum Beginn der Suche in eine passend gescopete Variable kopieren und nur bei Änderung updaten.
Den Text des Edits speichere ich schon zwischen: Suche.Text := AnsiUpperCase(Edit1.Text); "gescopete Variable kopieren und nur bei Änderung updaten" Verstehe ich nicht. Ich ändere doch nichts, ich informiere mich mal jetzt, was überhaupt eine gescopte Variable ist...

Schon mal Danke!
Jürgen
Indes sie forschten, röntgten, filmten, funkten, entstand von selbst die köstlichste Erfindung: der Umweg als die kürzeste Verbindung zwischen zwei Punkten. (Erich Kästner)
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#5

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 24. Sep 2008, 23:04
Er meint, du sollst bereits vor der Suche die Listbox.Items in einer StringList zwischenspeichern, am besten bereits konvertiert.
Du suchst dann in der Stringlist

Außerdem folgendes:
Delphi-Quellcode:
type
  TSuche = record
    Text: AnsiString;
    ItemPos: integer;
    StrPos: integer;
  end;
//...

var
  i, NextPos: Integer;
  ItemText: AnsiString;
begin
  if Suche.ItemPos = -1 then
    Suche.ItemPos := 0;
  Suche.Text := AnsiUpperCase(Edit1.Text); // Edit1 = Suchtext

  for i := Suche.ItemPos to Pred(Search_Form.Listbox.Count) do
  begin
    ItemText := AnsiUpperCase(Search_Form.Listbox.Items.Strings[i]);
    if Suche.StrPos > 0 then
    begin
      NextPos := pos(Suche.Text, Copy(ItemText, Suche.StrPos +
        length(Suche.Text), length(ItemText) - Suche.StrPos));
// vll. Nextpos = posex(Suche.Text im itemtext, nextpos + length(suche.text)) ???
// dann hier keine if abfrage, sondern einfach

      if NextPos > 0 then
        Suche.StrPos := NextPos; // siehe oben
      else
        Suche.StrPos := 0; // sinn? pos gibt doch nie werte < null zurück, oder?
    end
    else
      Suche.StrPos := pos(Suche.Text, ItemText);
....
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#6

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 24. Sep 2008, 23:32
Wie benutzerfreundlich ist denn eine Listbox mit 8000 Einträgen?
Michael
  Mit Zitat antworten Zitat
Benutzerbild von Hador
Hador

Registriert seit: 11. Dez 2004
Ort: Recke
682 Beiträge
 
Turbo Delphi für Win32
 
#7

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 25. Sep 2008, 05:10
Zitat von juergen:
Delphi-Quellcode:
[...]
      NextPos := pos(Suche.Text, Copy(ItemText, Suche.StrPos +
        length(Suche.Text), length(ItemText) - Suche.StrPos));
      if NextPos > 0 then
        Suche.StrPos := Suche.StrPos + length(Suche.Text) + NextPos - 1
      else
        Suche.StrPos := 0;
[...]
Da hast du aber zuerst einmal noch einen Fehler drin. Wenn der Suchtext "otto" ist und der durchsuchte Text "ottotto" enthält, so wird nur das erste Otto gefunden. Und um die Geschwindigkeit zu erhöhen könntest du den Copy-Befehl rausschmeißen und statt Delphi-Referenz durchsuchenPos mit Delphi-Referenz durchsuchenPosEx arbeiten:

Delphi-Quellcode:
[...]
      PosEx(Suche.Text, ItemText, Succ(Suche.StrPos));
      if NextPos > 0 then
        Suche.StrPos := Pred(NextPos) // Warum hier eigentlich einen weniger?
      else
        Suche.StrPos := 0;
[...]
Edit: Arrg, PosEx hatte jfheins ja schon genannt. Muss die Uhrzeit machen
Lars Kiesow
http://www.larskiesow.de

Computer gehorchen deinen Befehlen, nicht deinen Absichten.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#8

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 25. Sep 2008, 10:29
ListBox arbeitet intern mit einer Stringliste, es bringt also nichts, den Inhalt zu kopieren. Mit PosEx ist es sowieso viel schneller, denn der Bottleneck ist eindeutig die Verwendung von 'Copy'.

Ich habe den Code mal mit PosEx mit 20.000 Zeilen getestet (600k Text), Ohne Begin/EndUpdate, Suche direkt in der Listbox. Ergebnis: 200ms, um ein nicht existentes Wort in dem Text zu finden.

Dann habe ich den Text der Listbox vorher in einen String kopiert (fText := MyListBox.Items.Text). Das dauert 350ms. Dafür dauert das Suchen dann direkt in diesem String gemessene 0ms (also nicht meßbar).

Fazit: Wenn Du in einer sich nicht häufig ändernden Liste suchst, würde ich den Umweg über die Konvertierung in einen String gehen, sonst eben direkt in der Liste suchen (mit For-Schleife und PosEx).
Delphi-Quellcode:
procedure TForm1.btFindFirstClick(Sender: TObject);
begin
  fText := lb.items.text;
  fPos := 0;
  btSearchAgainClick(Sender);
end;


procedure TForm1.btFindAgainClick(Sender: TObject);
Var
  p,iLine,iCol : Integer;

  Procedure _CalcLineAndCol (aPos : Integer; Var aLine, aCol : Integer);
  Var
    i, iLineStart : Integer;

  Begin
    aLine := 1;
    For i:=1 to aPos do
      If Ftext[i]=#10 Then Begin
        iLineStart := i;
        inc(aLine);
        End;
    aCol := aPos - iLineStart;
  End;

begin
  p := csstrings.PosEx(edSearch.Text, fText,fPos+1);
  if p>0 Then Begin
    _CalcLineAndCol(p, iLine, iCol);
    lb.TopIndex := max(iLine-3, 1);
    fPos := p+Length (edSearch.Text)-1;
  End Else Raise Exception.Create('Suchstring nicht gefunden');
end;
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von DGL-luke
DGL-luke

Registriert seit: 1. Apr 2005
Ort: Bad Tölz
4.149 Beiträge
 
Delphi 2006 Professional
 
#9

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 25. Sep 2008, 15:17
Scope ist der Gültigkeitsbereich einer Variable. Eine "entsprechend gescopete Variable" ist also eine, die den richtigen Gültigkeitsbereich hat, also für die ganze Suche gültig bleibt.

Der Sinn der Übung wäre, dafür zu sorgen, dass nicht bei jedem Suchvorgang auf eine Property zugegriffen werden muss. Aber alzaimar hat hier eine sicherlich ziemlich optimale Lösung gepostet.
Lukas Erlacher
Suche Grafiktablett. Spenden/Gebrauchtangebote willkommen.
Gotteskrieger gesucht!
For it is the chief characteristic of the religion of science that it works. - Isaac Asimov, Foundation I, Buch 1
  Mit Zitat antworten Zitat
jottkaerr

Registriert seit: 2. Jul 2007
Ort: Tuttlingen
81 Beiträge
 
Delphi 10.1 Berlin Professional
 
#10

Re: [Konzeptfrage] ist Listbox schneller zu durchsuchen?

  Alt 25. Sep 2008, 16:35
Zitat von alzaimar:
ListBox arbeitet intern mit einer Stringliste, es bringt also nichts, den Inhalt zu kopieren. Mit PosEx ist es sowieso viel schneller, denn der Bottleneck ist eindeutig die Verwendung von 'Copy'.
Hinter dem Items-Property von TListBox steckt ein TListBoxStrings-Objekt. Jeder Aufruf von dessen Get()- oder Put()-Methode löst einen Aufruf von SendMessage() aus. Dies mag zwar langsam sein, aber ein Umkopieren bringt in diesem Fall tatsächlich nichts, weil im Originalcode bereits immer nur einmal auf jedes Element zugegriffen wurde. Dieser eine Zugriff pro Element wäre auch beim Umkopieren in eine TStringList notwendig.

jkr
Jürgen Krämer
Sometimes I think the surest sign that intelligent life exists elsewhere
in the universe is that none of it has tried to contact us. (Calvin)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:09 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