Einzelnen Beitrag anzeigen

Benutzerbild von leddl
leddl

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

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

  Alt 18. Apr 2005, 16:47
Hm, komisch. Bei mir hat das immer ganz gut funktioniert. Sicher, daß der gesuchte Begriff auch enthalten ist? Vielleicht hast du halt immer als 2. Item einen recht ähnlichen String.

//Edit:
Also weil du mich jetzt verunsichert hast, hab ich mich hingehockt und es mal ausprobiert. Funktioniert bei mir immer noch genau so, wie es soll. Selbst bei Verunstaltung der Wörter bekomme ich immer noch den richtigen Index angezeigt.

//Edit2:
Mist, jetzt hab ich grade erst deinen Zusatz gesehen. OK, dann halt noch ein Edit.
Was meintest du damit? Die Ausgabe bekommst du hin, indem du aus den TStrings denjenigen ausliest, dessen Index zurückgeliefert wird. Levenshtein liefert dir immer nur ein - das beste - Ergebnis zurück und nicht mehrere, falls du das wolltest. Evtl kann man den Algorithmus aber auch so umbügeln, daß er alle Strings, die eine geringere Distanz als x haben in ein TStrings packt und zurückgibt. Sollte auch nicht allzuviel Aufwand bereiten.
Delphi-Quellcode:
function Similarest(aText: string; aList: TStrings; Treshold: Integer): TStrings;
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;

  for i := 0 to (Length(Dist)-1) do
    if (Dist[i] < Treshold) then Result.Items.Add(aList[i]);
    //Evtl hier noch zur Data-Eigenschaft die Distanz hinzufügen
end;
Ungetestet, sollte aber funktionieren.
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