Einzelnen Beitrag anzeigen

taveuni

Registriert seit: 3. Apr 2007
Ort: Zürich
533 Beiträge
 
Delphi 11 Alexandria
 
#1

Schneller Stringvergleich nach bestimmtem Muster

  Alt 9. Dez 2015, 11:05
Hallo zusammen,
Der Titel ist etwas bescheuert - mir ist aber nichts besseres eingefallen. Folgendes Szenario: Es werden automatisch irgendwelche Codes gescannt an verschiedenen Stellen - nennen wir diese Eingänge. Die Artikel werden befördert und kommen an Ausgänge an welchen sie wieder gescannt werden. Nun sollen Artikel welche an bestimmten Eingängen eingegangen sind automatisch an bestimmten Ausgängen gesondert behandelt werden. Soweit einfach - wir erhalten die Standorte sowie die Scancodes. Die Codes der definierten Eingänge sammeln wir in einem Pool. Wenn wir an einem Ausgang einen Code erhalten welcher im Pool ist reagieren wir entsprechend. Das Problem ist nun: Die Codes sind auf teilweise zerknittertem Papier aufgedruckt und werden teilweise unterschiedlich am Ein- und Ausgang gelesen. Alle Versuche seitens des Betreibers diese Fälle zu eliminieren sind gescheitert. Deshalb müssen wir neu wenn wir keinen Match haben auch noch nach einem bestimmten Muster suchen. Wenn dieses zutrifft wird angenommen dass es sich um den identischen (aber unterschiedlich gelesenen) Code handelt. Ich habe mir eine Funktion zusammengeschustert welche funktioniert. Allerdings: Wir erhalten im Durchschnitt 10000 Scans pro Minute. Im Pool können bis zu 30000 Codes sein. Ich muss diesen Vergleich so schnell wie möglich machen. Kann man die Funktion bezüglich Geschwindigkeit optimieren? Folgend ein Beispiel:

Eingangs-Scan: XX123456

Wahrheitstabelle Ausgangs-Scan:

GelesenGültig
XY123456Ja
X123456Ja
XX1234567Ja
Y123456Nein
XX1234Nein

Die bisherige Funktion:
Delphi-Quellcode:
function MatchRule(const BaseStr: String; const CompareList: TStringList): Boolean;
var
  i,j, cntForward, cntBackward: Integer;
  lBase, lComp: Integer;
  StrBase, StrCompare: String;
begin
  Result:= False;
  lBase:= Length(BaseStr);
  for i := 0 to CompareList.Count -1 do
  begin
    lComp:= Length(CompareList[i]);
    if InRange(lBase - lComp,-1,1) then
    begin
      cntForward:= 0;
      cntBackward:= 0;
      if lBase <= lComp then
      begin
        StrBase:= BaseStr;
        StrCompare:= CompareList[i];
      end
      else
      begin
        StrBase:= CompareList[i];
        StrCompare:= BaseStr;
      end;

      // compare contains base
      if Length(StrBase) < Length(StrCompare) then
        Result:= Pos(StrBase, StrCompare) > 0;

      if not Result then
      begin
        // check forward
        for j := 1 to Length(StrBase) -1 do
        begin
          if StrBase[j] = StrCompare[j] then
            inc(cntForward)
          else break;
        end;

        // check backward
        for j := Length(StrBase) downto 1 do
        begin
          if StrBase[j] = StrCompare[j+(Length(StrCompare) - Length(StrBase))] then
            inc(cntBackward)
          else break;


        if lBase = lComp then
          Result:= (cntForward + cntBackward) >= (Length(StrBase) -1)
        else
          Result:= (cntForward + cntBackward) = Length(StrBase);
        end;

      end;
      if Result then Exit;
    end
    else Continue;

  end;
end;
Die Codes können 3-12 stellig sein und beginnen meistens mit Buchstaben.

Die Ansätze welche ich mir zur Verbesserung überlegt habe:
- Sollte ich die Liste zuerst nach dem Anfang des zu prüfenden Strings sortieren?
- Sollten die Längen des Strings zuerst in Variablen gespeichert werden um das dauernde Length() zu vermeiden?
- What else?

Danke für Eure Hilfe
Die obige Aussage repräsentiert meine persönliche Meinung.
Diese erhebt keinen Anspruch auf Objektivität oder Richtigkeit.
  Mit Zitat antworten Zitat