2012-05-14 22 views
10

Quiero crear una función en Delphi que calcule diferentes niveles de dos cadenas. Si dos cadenas son iguales (ignorando el caso), entonces debería devolver 0, pero si no son iguales, debería devolver el número de caracteres diferentes. Esta función puede ser muy útil para verificar la ortografía. código¿Cómo puedo calcular una diferencia entre dos cadenas?

function GetDiffStringLevel(S1,S2:string):Integer; 
begin 
    if SameText(S1,S2) then Exit(0); 
    // i want get different chars count 
end 

muestras:

Diff:=GetDiffStringLevel('Hello','Hello');// Diff:=0; 
Diff:=GetDiffStringLevel('Hello','2Hello');// Diff:=1; 
Diff:=GetDiffStringLevel('Hello','H2ello');// Diff:=1; 
Diff:=GetDiffStringLevel('Hello','Hello W');// Diff:=2; 
Diff:=GetDiffStringLevel('Hello','World');// Diff:=6; or 5 
+2

Vea también: [Necesita una rutina para detectar cadenas que son similares pero no idénticas] (http://stackoverflow.com/q/10402858/576719). –

Respuesta

12

aplicación rápida y compacta.

Aproximadamente 3 veces más rápido que la implementación de smasher con cadenas normales. Más de 100 veces más rápido si una de las cadenas está vacía.

La función de Smasher no distingue entre mayúsculas y minúsculas, lo que también puede ser útil.

function LevenshteinDistance(const s, t: string): integer;inline; 
var 
    d : array of array of integer; 
    n, m, i, j : integer; 
begin 
    n := length(s); 
    m := length(t); 
    if n = 0 then Exit(m); 
    if m = 0 then Exit(n); 

    SetLength(d, n + 1, m + 1); 
    for i := 0 to n do d[i, 0] := i; 
    for j := 0 to m do d[0, j] := j; 

    for i := 1 to n do 
    for j := 1 to m do 
     d[i, j] := Min(Min(d[i-1, j]+1, d[i,j-1]+1), d[i-1,j-1]+Integer(s[i] <> t[j])); 

    Result := d[n, m]; 
end; 

Nota: la directiva inline reduce el tiempo de ejecución a menos del 70% en mi máquina, pero sólo para la plataforma de destino Win32. Si compila hasta 64bits (Delphi XE2), la alineación la hace un poco más lenta.

7

Lo que se quiere que se conoce como la Levenshtein distance (el número mínimo de ediciones para transformar una cadena en la otra, en una edición es o bien una inserción carácter, eliminación carácter o sustitución de personaje). El sitio de wikipedia tiene una implementación de pseudo código.

aplicación Delphi:

function LevenshteinDistance(String1 : String; String2 : String) : Integer; 

var 
    Length1, Length2  : Integer; 
    WorkMatrix   : array of array of Integer; 
    I, J     : Integer; 
    Cost     : Integer; 
    Val1, Val2, Val3  : Integer; 

begin 
String1 := TCharacter.ToUpper (String1); 
String2 := TCharacter.ToUpper (String2); 
Length1 := Length (String1); 
Length2 := Length (String2); 
SetLength (WorkMatrix, Length1+1, Length2+1); 
for I := 0 to Length1 do 
    WorkMatrix [I, 0] := I; 
for J := 0 to Length2 do 
    WorkMatrix [0, J] := J; 
for I := 1 to Length1 do 
    for J := 1 to Length2 do 
    begin 
    if (String1 [I] = String2 [J]) then 
     Cost := 0 
    else 
     Cost := 1; 
    Val1 := WorkMatrix [I-1, J] + 1; 
    Val2 := WorkMatrix [I, J-1] + 1; 
    Val3 := WorkMatrix[I-1, J-1] + Cost; 
    if (Val1 < Val2) then 
     if (Val1 < Val3) then 
     WorkMatrix [I, J] := Val1 
     else 
     WorkMatrix [I, J] := Val3 
    else 
     if (Val2 < Val3) then 
     WorkMatrix [I, J] := Val2 
     else 
     WorkMatrix [I, J] := Val3; 
    end; 
Result := WorkMatrix [Length1, Length2]; 
end; 
+2

@MajidTaheri: solicitó una función que calcule la diferencia entre dos palabras, y la función de Smasher es la respuesta a su pregunta. Nunca dijiste en tu pregunta * cómo exactamente * usarías la función. –

+2

@MajidTaheri, puede probar [esto] (http://stackoverflow.com/a/54798/576719) implementación de 'Levenshtein Distance'. –

+0

@LU RD, la función EditDistance es mejor. – MajidTaheri

Cuestiones relacionadas