Gracias a smirkingman para el buen puesto código. Aquí hay una versión optimizada.
1) Uso Asc (Mid $ (s1, i, 1) en su lugar. Comparación numérico es generalmente más rápido que el texto.
2) Uso Mediados $ Istead de Mid ya que la tarde es la variante ver. y agregar $ es string ver.
3) Utilice la función de aplicación durante mín. (solo preferencia personal)
4) Use Long en vez de números enteros, ya que es lo que se usa de forma excelente.
Function Levenshtein(ByVal string1 As String, ByVal string2 As String) As Long
Dim i As Long, j As Long
Dim string1_length As Long
Dim string2_length As Long
Dim distance() As Long
string1_length = Len(string1)
string2_length = Len(string2)
ReDim distance(string1_length, string2_length)
For i = 0 To string1_length
distance(i, 0) = i
Next
For j = 0 To string2_length
distance(0, j) = j
Next
For i = 1 To string1_length
For j = 1 To string2_length
If Asc(Mid$(string1, i, 1)) = Asc(Mid$(string2, j, 1)) Then
distance(i, j) = distance(i - 1, j - 1)
Else
distance(i, j) = Application.WorksheetFunction.Min _
(distance(i - 1, j) + 1, _
distance(i, j - 1) + 1, _
distance(i - 1, j - 1) + 1)
End If
Next
Next
Levenshtein = distance(string1_length, string2_length)
End Function
ACTUALIZACIÓN:
Para aquellos que lo deseen: Creo que es seguro decir que la mayoría de la gente utiliza para calcular la distancia Levenshtein porcentajes coincidencia parcial. Aquí hay una manera de hacerlo, y he agregado una optimización para que pueda especificar el mínimo. match% to return (valor predeterminado es 70% +. Ingrese porcentajes como "50" u "80", o "0" para ejecutar la fórmula independientemente).
El aumento de velocidad proviene del hecho de que la función comprobará si es posible incluso que esté dentro del porcentaje que usted le da al verificar la longitud de las 2 cuerdas. Tenga en cuenta que hay algunas áreas donde se puede optimizar esta función, pero la he mantenido en este punto por razones de legibilidad. Me concatenan la distancia en consecuencia para la demostración de la funcionalidad, pero se puede jugar con él :)
Function FuzzyMatch(ByVal string1 As String, _
ByVal string2 As String, _
Optional min_percentage As Long = 70) As String
Dim i As Long, j As Long
Dim string1_length As Long
Dim string2_length As Long
Dim distance() As Long, result As Long
string1_length = Len(string1)
string2_length = Len(string2)
' Check if not too long
If string1_length >= string2_length * (min_percentage/100) Then
' Check if not too short
If string1_length <= string2_length * ((200 - min_percentage)/100) Then
ReDim distance(string1_length, string2_length)
For i = 0 To string1_length: distance(i, 0) = i: Next
For j = 0 To string2_length: distance(0, j) = j: Next
For i = 1 To string1_length
For j = 1 To string2_length
If Asc(Mid$(string1, i, 1)) = Asc(Mid$(string2, j, 1)) Then
distance(i, j) = distance(i - 1, j - 1)
Else
distance(i, j) = Application.WorksheetFunction.Min _
(distance(i - 1, j) + 1, _
distance(i, j - 1) + 1, _
distance(i - 1, j - 1) + 1)
End If
Next
Next
result = distance(string1_length, string2_length) 'The distance
End If
End If
If result <> 0 Then
FuzzyMatch = (CLng((100 - ((result/string1_length) * 100)))) & _
"% (" & result & ")" 'Convert to percentage
Else
FuzzyMatch = "Not a match"
End If
End Function
Este código funciona arrastrando y soltando para Access VBA también. :) – HelloW
Nota rápida para usuarios futuros, VBA 'Integer' declara * debería * usar menos memoria y ser más rápido, pero ahora se convierten automáticamente a 'Long' tipo detrás de escena (fuente: [MSDN] (https: // msdn) .microsoft.com/es-us/library/office/aa164506 (v = office.10) .aspx), consulte [this] (http://stackoverflow.com/a/26409520/6609896) también). Por lo tanto, para aumentar el rendimiento marginal, declararlos como "Largos" guarda el tiempo de conversión interno (algunas otras respuestas que veo han hecho uso de esto). O, si sus cadenas tienen menos de 255 caracteres de longitud, declare como 'Bytes' ya que esto requiere incluso menos memoria que 'Integer'. – Greedo