| Autor |
Beitrag |
Flamefire
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Mi 01.10.08 10:39
Hallo,
ich habe einen stringvergleich, der sehr häufig ausgeführt werden muss
darum die Frage, was das schnellste (Ausführung) ist.
Es geht darum, dass ein String am Anfang eines anderen sein soll: z.B. "abc" ind "abcde" aber nicht ind "deabc"
Pos() würde den ganzen string durchsuchen-->unperformant
Habs z.Zt. so:
Copy(sTarget,1,Length(sSuch))<>sSuch
wobei sSuch ne konstante ist
aber vermutlich ist das sogar noch langsamer...
Was wäre die beste?
|
|
Gausi
      
Beiträge: 8554
Erhaltene Danke: 481
Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
|
Verfasst: Mi 01.10.08 10:44
In den StrUtils gibt es Funktionen AnsiStartsText und AnsiStartsStr (evtl. ohne das s in Starts und/oder leicht anders) - der Unterschied liegt bei der Berücksichtigung von Groß- und Kleinschreibung.
Oder halt eine eigene kleine Funktion schreiben. Mit einer Schleife, die sofort abbricht, sobald ein Zeichen nicht übereinstimmt.
_________________ We are, we were and will not be.
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 01.10.08 10:46
Z.B. so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| function StartsWith(const s, Pattern: string): Boolean; var i: integer; begin i := 0; Result := Length(Pattern) <= Length(s); while (i < Length(Pattern)) and Result do begin inc(i); Result := s[i] = Pattern[i]; end; end; |
|
|
Flamefire 
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Mi 01.10.08 11:10
Die funtion von DeddyH sieht nicht schlecht aus
wie funktioniert der Zugriff auf String[x]?
Wäre man vl mit Pointern schneller? Oder ist das schon das gleiche?
Die funktionen ansistarts...() sind das gleiche was ich auch schon gemacht hab...
nur vermutlich noch langsamer...
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 01.10.08 11:15
Pointer oder Streams wären vermutlich noch schneller. Du könntest z.B. beide Strings in jeweils einen Stream laden, der die Länge Length(Pattern) hat. Nun könntest Du mit CompareMem vergleichen. Und die Frage nach dem Zugriff auf String[x] habe ich nicht verstanden, was meinst Du?
|
|
Flamefire 
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Mi 01.10.08 11:30
also der string hat eine Länge von ca. 10-15 Zeichen. bei streams würde ich denken, dauert es zu lange...weil der stream muss ja erst erstellt werden, dann verglichen etc...
und so weit ich weiß ist ein string einfach nur ein pchar
sprich: der string ist ein pointer auf eine zeichenfolge
man könnte also: Länge vergleichen (von dem einen ist es ja ne konstante)
und dann jeweils 4-byte bis 2- und 1-byte weise den inhalt der pointer vergleichen
also so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| s:='String'; s2:='String2'; pb:=Cardinal(Pointer(s)); pb2:=Cardinal(Pointer(s2)); If(PCardinal(pb)^=PCardinal(pb2)^ and PWord(pb+4)^=PWord(pb2+4)^) |
Oder liege ich da falsch?
|
|
DeddyH
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mi 01.10.08 12:00
Versuch es doch einfach mal so:
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| function StartsWith(const s, Pattern: string): Boolean; begin Result := Length(Pattern) <= Length(s); if Result then Result := CompareMem(PChar(s),PChar(Pattern),Length(Pattern)); end; |
|
|
Flamefire 
      
Beiträge: 1207
Erhaltene Danke: 31
Win 10
Delphi 2009 Pro, C++ (Visual Studio)
|
Verfasst: Mi 01.10.08 12:31
jo super idee
hab mal nen test gemacht:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
| procedure TfrmMain.Button1Click(Sender: TObject); var i,k:Integer;j:Cardinal; s,str1:String; begin str1:='TestString'; s:='TestString1'; j:=GetTickCOunt; k:=0; for i:=0 to 9999999 do begin If(Copy(s,1,Length(str1))=str1) then Inc(k); end; s:='Test134'; for i:=0 to 9999999 do begin If(Copy(s,1,Length(str1))=str1) then Inc(k); end; Caption:=inttostr(GetTickDiff(j,GetTickCOunt))+' '+inttostr(k); end;
procedure TfrmMain.Button2Click(Sender: TObject); var i,k:Integer;j:Cardinal; s,str1:String; begin str1:='TestString'; s:='TestString1'; j:=GetTickCOunt; k:=0; for i:=0 to 999999 do begin If(CompareMem(Pointer(s),Pointer(str1),Length(str1))) then Inc(k); end; s:='Test134'; for i:=0 to 999999 do begin If(CompareMem(Pointer(s),Pointer(str1),Length(str1))) then Inc(k); end; Caption:=inttostr(GetTickDiff(j,GetTickCOunt))+' '+inttostr(k); end; |
Ergebnis: Methode 1: ~3300
Methode 2: ~80(!!!)
Also: Gelöst!
|
|
elundril
      
Beiträge: 3747
Erhaltene Danke: 123
Windows Vista, Ubuntu
Delphi 7 PE "Codename: Aurora", Eclipse Ganymede
|
Verfasst: Mi 01.10.08 12:52
wow, dachte nicht das es da so einen performanceunterschied gibt. werd das mir mal gleich wegspeichern!
_________________ This Signature-Space is intentionally left blank.
Bei Beschwerden, bitte den Beschwerdebutton (gekennzeichnet mit PN) verwenden.
|
|