Einzelnen Beitrag anzeigen

Benutzerbild von leddl
leddl

Registriert seit: 13. Okt 2003
Ort: Künzelsau
1.613 Beiträge
 
Delphi 2006 Professional
 
#19

Re: Ähnlichkeitssuche: Fuzzy-Search-Unit???

  Alt 18. Apr 2005, 14:03
War ich das? Glaub schon, oder? Zumindest benutz ich die auch und hab sie auch mal hier irgendwo gepostet. Von wem ich die Funktion hab, weiß ich auch nicht mehr, aber sie funktioniert ganz gut.
Wollte das hier aber nicht posten, da er ja eigentlich eben die FuzzySearch benutzen wollte... ne Moment mal, hat er ja so gar nich gesagt... er hat halt nur die gefunden.
Dann kann man den Levenshtein nur empfehlen. Funktioniert wie gesagt wunderbar.
...
So, hab gekramt und mal meine Funktion rausgesucht. Is im Endeffekt das gleiche, nur hab ich das alles innerhalb einer Gesamtfunktion zusammengefasst, so daß nur noch ein Aufruf benötigt wird.
Die folgende Funktion benötigt als Parameter den zu suchenden String und eine TStrings. Der Rückgabewert ist dann der Index des ähnlichsten TStrings-Elements.
Die Funktion läßt sich natürlich nach Belieben anpassen, mir hat sie so aber ganz gute Dienste erwiesen.
Delphi-Quellcode:
{ ---  Sucht in einer Liste nach dem ähnlichsten Text  ----------------------- }
function Similarest(aText: string; aList: TStrings): Integer;
var
  Dummy: string;
  MinV : Integer;
  i : Integer;
  FiR0 : Integer;
  FiP0 : Integer;
  FiQ0 : Integer;
  Dist : array of Integer;

  { ---  Similarest: Subprozedure  ------------------------------------------- }
  procedure LevenshteinPQR(p,q,r:integer);
  begin
    FiP0 := p;
    FiQ0 := q;
    FiR0 := r;
  end; {  LevenshteinPQR  }


  { ---  Similarest: Subfunktion  -------------------------------------------- }
  function LevenshteinDistance(const sString,sPattern: String): Integer;
  const
    MAX_SIZE = 50;
  var
    aiDistance: array [0..MAX_SIZE,0..MAX_SIZE] of Integer;
    i,j,
    iP,iQ,iR,iPP,
    iStringLength,
    iPatternLength,
    iMaxI,iMaxJ : Integer;
    chChar : Char;

    function Min(X,Y,Z: Integer): Integer;
    begin
      if (X<Y) then
        Result:=X
      else
        Result:=Y;
      if (Result>Z) then
        Result:=Z;
    end; {  Min  }

  begin
    iStringLength:=length(sString);
    if (iStringLength>MAX_SIZE) then
      iMaxI:=MAX_SIZE
    else
      iMaxI:=iStringLength;
    iPatternLength:=length(sPattern);
    if (iPatternLength>MAX_SIZE) then
      iMaxJ:=MAX_SIZE
    else
      iMaxJ:=iPatternLength;

    aiDistance[0, 0]:=0;
    for i:=1 to iMaxI do
      aiDistance[i, 0]:=aiDistance[i-1, 0]+FiR0;
    for j:=1 to iMaxJ do begin
      chChar:=sPattern[j];
      if ((chChar='*') or (chChar='?')) then
        iP:=0
      else
        iP:=FiP0;
      if (chChar='*') then
        iQ:=0
      else
        iQ:=FiQ0;
      if (chChar='*') then
        iR:=0
      else
        iR:=FiR0;

      aiDistance[0, j]:=aiDistance[0, j-1]+iQ;

      for i:=1 to iMaxI do begin
        if (sString[i]=sPattern[j]) then
          iPP:=0
        else
          iPP:=iP;
        {*** aiDistance[i,j] := Minimum of 3 values ***}
        aiDistance[i,j]:=Min(aiDistance[i-1, j-1]+iPP,
                             aiDistance[i, j-1] +iQ,
                             aiDistance[i-1, j] +iR);
      end;
    end;
    Result:=aiDistance[iMaxI, iMaxJ];
  end; {  LevenshteinDistance  }
begin
  SetLength(Dist, aList.Count);
  LevenshteinPQR(1, 1, 1);

  for i := 0 to (aList.Count-1) do
  begin
    //Dummy := ExtractFileName(aList.Strings[i]);
    //Dummy := Copy(Dummy, 1, Pos('.', Dummy)-1);
    Dummy := aList.Strings[i];

    Dist[i] := LevenshteinDistance(aText, Dummy);
  end;

  MinV := 0;
  for i := 0 to (Length(Dist)-1) do
    if (Dist[MinV] > Dist[i]) then MinV := i;

  Result := MinV;
end;
Ich möchte aber auch nochmal darauf hinweisen, daß diese Funktion nicht von mir stammt. Leider hab ich wie gesagt, vergessen, wo ich sie herhabe. Falls das also jemandem bekannt vorkommt, soll er mir bescheid sagen. Dann kann ich auch gerne einen kleinen Vermerk einfügen.

@glkgereon:
Sachte sachte! Er hat sichs wohl nich richtig angeschaut. Ich übrigens auch nicht. Aber Respekt, du warst uns allen voraus.
Axel Sefranek
A programmer started to cuss, cause getting to sleep was a fuss.
As he lay there in bed, looping round in his head
was: while(!asleep()) ++sheep;
  Mit Zitat antworten Zitat