[gelöst] Schnelles Vergleichen/Suchen von Listeneinträgen

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

[gelöst] Schnelles Vergleichen/Suchen von Listeneinträgen

Beitrag von Scotty »

Ich habe in etwa folgende Datenstruktur:

Code: Alles auswählen

TData=class
  property A:integer;
  property B:array[0..3] of byte;
  property C:char;
end;
 
TOneData=record
  Sum : integer;
  Text : string;
  Data : TList; //of TData
end;
 
FAllData : TList; //of TOneData
Nun kommt es vor, dass Einträge zur Liste hinzugefügt werden sollen, die schon drin sind. Das versuche ich zu vermeiden, indem ich alle Items vergleiche:

Code: Alles auswählen

function CompareData(aData,bData:TOneData):boolean;
begin
  Result:=false;
  if aData.Sum=bData.Sum and
     aData.Text=bData.Text and
     aData.Data.Count=bData.Data.Count then
  begin
    for i:=0 to aData.Data.Count-1 do 
     if TData(aData.Data[i]).A=TData(bData.Data[i]).A and //die Reihenfolge ist festgelegt
    ... then 
       Result:=true;
  end; 
end;
Das dauert allerdings eine Ewigkeit bei 100000 Einträgen. Mit CompareMem() habe ich immer gleich als Ergebnis bekommen und bin mir gar nicht sicher, ob das hier benutzt werden kann. Wie macht man so etwas schneller?
Zuletzt geändert von Scotty am Mi 24. Feb 2010, 17:03, insgesamt 1-mal geändert.

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6835
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Schnelles Vergleichen/Suchen von Listeneinträgen

Beitrag von af0815 »

Hash bilden und Liste sortieren. Anhand vom Hash sieht man ob es unterschiedliche Einträge sind, ohne jedes Teilelement vergleichen zu müssen. Wenn du auch noch nach den Hash sortierst, so kann du sehr rasch suchen.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Schnelles Vergleichen/Suchen von Listeneinträgen

Beitrag von Scotty »

Kannst du mal bitte ein Beispiel für Hash zeigen? Ich vermute integer*Konstante+ord(char)*Konstante etc.

Benutzeravatar
theo
Beiträge: 10904
Registriert: Mo 11. Sep 2006, 19:01

Re: Schnelles Vergleichen/Suchen von Listeneinträgen

Beitrag von theo »

Bin kein Experte, aber vllt. hilft das:
http://www.freepascal.org/docs-html/fcl ... table.html" onclick="window.open(this.href);return false;

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6835
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Schnelles Vergleichen/Suchen von Listeneinträgen

Beitrag von af0815 »

Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Hitman
Beiträge: 512
Registriert: Mo 25. Aug 2008, 18:17
OS, Lazarus, FPC: ArchLinux x86, WinVista x86-64, Lazarus 0.9.29, FPC 2.4.1
CPU-Target: x86
Wohnort: Chemnitz

Re: Schnelles Vergleichen/Suchen von Listeneinträgen

Beitrag von Hitman »

Man braucht nicht unbedingt Hashes. Wenn man die Objekte der Liste eindeutig Sortieren kann, hat man im Prinzip schon einen Binärbaum den man also mit einer Komplexität von O(log n) durchsuchen kann.
Da die Daten in deinem Fall sehr schön vergleichbar und damit sortierbar sind, dürfte das eigentlich ideal sein.

Scotty
Beiträge: 768
Registriert: Mo 4. Mai 2009, 13:24
OS, Lazarus, FPC: Arch Linux, Lazarus 1.3 r44426M FPC 2.6.4
CPU-Target: x86_64-linux-qt/gtk2
Kontaktdaten:

Re: Schnelles Vergleichen/Suchen von Listeneinträgen

Beitrag von Scotty »

Auf die (viel einfachere) Lösung hat mich Andreas' Link gebracht. Ich sortiere jetzt die Liste zuerst und vergleiche dann von 1..Count-1 mit dem Vorgänger. Das dauert etwa eine halbe Sekunde (n Vergleiche) gegenüber 2min vorher (n*m Vergleiche). Warum der Unterschied so erheblich ist, verstehe ich allerdings nicht. Danke für alle Antworten!

Antworten