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.