Robert Bamler: 2 Strings PROZENTUAL vergleichen...

Beitrag lesen

Hallo,

Ich möchte zwei Strings prozentual vergleichen. Und wenn der eine String 80% mit dem anderen String übereinstimmt, soll er angezeigt werden, wenn nicht, dann eben nicht.

Ich hab' so etwas ähnliches einmal mit Delphi geschrieben, und zwar hat es mir Verbesserungsvorschläge gesucht, wenn die Rechtschreibkorrektur einen Fehler gefunden hat (ähnlich wie bei großen Textverarbeitungsprogrammen wie Word). Dabei ging ich so vor:

Ich habe mir überlegt, was ein Mensch alles für fehler machen kann. Dabei bin ich zu folgendem Ergebnis gekommen: Der Mensch kann

  • einen Buchstaben zu viel einfügen. Beispiel: "Fehrler"
  • einen Buchstaben auslassen. Beispiel: "Feler"
  • zwei aufeinanderfolgende Buchstaben vertauschen. Beispiel: "Fheler"
  • einen falschen Buchstaben schreiben. Beispiel: "Vehler"

Die ersten beiden Fälle sind genau entgegengesetzt und können daher als gleich betrachtet werden: Wenn das Wort "Fehrler" mit dem richtigen Wort "Fehler" verglichen wird, kann man sagen, dass im Wort "Fehrler" ein r zu viel geschrieben wurde, man könnte aber genauso gut sagen, dass im Wort "Fehler" ein r ausgelassen wurde.

Dann habe ich eine Funktion geschrieben, die als Parameter zwei Wörter übergeben bekommt, nämlich das falsch geschriebene Wort und das Vergleichswort. Diese Funktion ermittelt zu erst, wie lange das falsch geschriebene Wort ist und multipliziert diesen Wert mit einer festen Konstante (bei dir wären dass 35%, also 0.35). Damit weis die Funktion, wie viele der oben genannten Unterschiede zwischen den beiden Wörtern erlaubt sind. Die anzahl dieser Unterschiede wird in einem imaginären Unterschiedswert gespeichert, der zu Anfang 0 ist.

Die Funktion vergleicht nun die länge der beiden Wörter, um zu ermitteln, welches Wort das längere und welches das kürzere ist. Falls der Längenunterschied größer ist als die erlaubte Anzahl von Fehlern, wird abgebrochen.

Anschließend werden für beide Wörter je ein Zähler initialisiert, der immer angibt, an welcher Position im Wort (d.h. beim wie vielten Buchstaben) sich das Programm momentan befindet. Diese beiden Zähler werden auf den ersten Buchstaben gesetzt (bei Delphi ist das 1, bei JavaScript wäre das 0).

Jetzt kommt eine Schleife, in der jeder einzelne Buchstabe mehr oder weniger der Reihe nach durchlaufen wird, bis der Zähler des kürzeren Wortes größer ist, als die länge des kürzeren Wortes, d.h. bis das kürzere Wort abgearbeitet ist. Diese Schleife läuft folgendermaßen ab:

  • Es werden die durch die jeweiligen Zähler angegebenen Buchstaben   der beiden Wörter verglichen. Ist hier kein Unterschied, so werden   beide Zähler um eins erhöt und es wird mit dem nächsten   Schleifendurchlauf fortgefahren.

  • Falls die verglichenen Buchstaben unterschiedlich sind, wird der   imaginäre Unterschiedswert zwischen den beiden Wörter um eins   erhöht und folgendes überprüft:

- Stimmt der aktuelle Buchstabe des kürzeren Wortes mit dem     nächsten Buchstaben des längeren Wortes und stimmt der nächste     Buchstabe des kürzeren Wortes mit dem übernächsten Buchstaben des     längeren Wortes überein?     -> In diesem Fall wurde im kürzeren Wort ein Buchstabe        ausgelassen oder es wurde im längeren Wort ein Buchstabe zu        viel geschrieben. Der Zähler des kürzeren Wortes wird um 2,        der Zähler des längeren Wortes um 3 erhöht und es wird mit dem        nächsten Schleifendurchlauf fortgefahren.     (hier wird davon ausgegangen, dass ein zu viel geschriebener     Buchstabe nur im längeren Wort vorkommen, bzw. ein ausgelassener     Buchstabe nur im kürzeren Wort "vorkommen" kann, was ja auch am     wahrscheinlichsten ist.)

- Stimmt der nächste Buchstabe des kürzeren Wortes mit dem     aktuellen Buchstaben des längeren Wortes überein und stimmt der     aktuelle Buchstabe des kürzeren Wortes mit dem nächsten     Buchstaben des längeren Wortes überein?     -> In diesem Fall wurden zwei aufeinanderfolgende Buchstaben        vertauscht. Die Zähler beider Wörter werden um 2 erhöht und es        wird mit dem nächsten Schleifendurchlauf fortgefahren.

- Traf keine der bisher genannten Bedingungen zu, so wurde schlicht     ein falscher Buchstabe eingegeben. Der Zähler beider Wörter wird     um eins erhöht und es wird mit dem nächsten Schleifendurchlauf     forgefahren.

Zwischendrin wird immer wieder überprüft, ob die Anzahl der bisher gefundenen Fehler die Anzahl der zulässigen Fehler nicht überschreitet. Sobald die Anzahl der zulässigen Fehler überschritten wird, wird abgebrochen.

Die Funktion sieht im (ObjectPascal-)Quelltext folgendermaßen aus. Auch wenn es eine andere Programmiersprache ist, sollte es relativ leicht verständlich sein, da nur primitive Anweisungen verwendet wurden. Falls der Grenzwert überschritten wurde, wird -1 zurückgegeben, ansonsten wird die Anzahl der gefundenen Fehler (also der imaginäre Unterschiedswert) zurückgegeben.

function vergleicheWoerter(wort1,wort2: string): integer;                       // in wort1 muss das falsch geschriebene Wort übergeben werden, in wort2 muss das vergleichswort übergeben werden var laenge1, laenge2, laengenunterschied, zspeicher2: integer;     zspeicher: string;     pos1,pos2: integer;     vergleichmax: integer; begin      laenge1 := length(wort1);      laenge2 := length(wort2);      vergleichmax := Round(laenge1*minrichtigAnteil);      if vergleichmax = 0 then  vergleichmax := 1;

laengenunterschied := laenge1 - laenge2;      if (laengenunterschied > vergleichmax) or (laengenunterschied < -vergleichmax) then      begin           Result := -1;           exit;      end;

Result := 0;

if laengenunterschied < 0 then      begin           zspeicher := wort1;           wort1 := wort2;           wort2 := zspeicher;

zspeicher2 := laenge1;           laenge1 := laenge2;           laenge2 := zspeicher2;

laengenunterschied := -laengenunterschied;      end;

pos1 := 1;      pos2 := 1;

while pos2 <= laenge2 do      begin           if wort1[pos1] <> wort2[pos2] then           begin                Result := Result + 1;                if Result > vergleichmax then                begin                     Result := -1;                     exit;                end;

if (laengenunterschied > 0) and                                  // falls ein wort länger ist als das andere und nicht bereits genug fehlende buchstaben gefunden wurden                   (wort1[pos1+1] = wort2[pos2]) and                             // und falls der nächste buchstabe (immer vorhanden) übereinstimmen würde                   ((pos2 = laenge2) or (wort1[pos1+2] = wort2[pos2+1])) then    // und falls der übernächste buchstabe des längeren wortes (sofern vorhanden) mit dem nächsten des kürzeren wortes übereinstimmen würde:                begin                                                            // wort1 enthält einen buchstaben zu viel                     pos1 := pos1 + 1;                                           // einen buchstaben überspringen                     laengenunterschied := laengenunterschied - 1;                end                else if (pos2 <= laenge2-1) and                                  // falls noch mindestens ein buchstabe danach kommt                        (wort1[pos1+1] = wort2[pos2]) and (wort1[pos1] = wort2[pos2+1]) then // und falls zwei aufeinanderfolgende buchstaben vertauscht wurden:                begin                                                            // es wurden zwei aufeinanderfolgende Buchstaben vertauscht.                     pos1 := pos1 + 1;                     pos2 := pos2 + 1;                end;           end;

pos1 := pos1 + 1;           pos2 := pos2 + 1;      end;

Result := Result + laenge1 - pos1 + 1;      if Result > vergleichmax then  Result := -1; end;

Robert