Nhờ smirkingman cho mã bưu tốt đẹp. Đây là một phiên bản được tối ưu hóa.
1) Sử dụng Asc (Mid $ (s1, i, 1) để thay thế. So sánh bằng số thường nhanh hơn so với văn bản.
2) Sử dụng trung $ istead của trung kể từ sau là phiên bản ver. và thêm $ là chuỗi ver.
3) Sử dụng chức năng ứng dụng cho phút. (chỉ sở thích cá nhân)
4) Sử dụng Dài thay vì Số nguyên vì đó là những gì excel sử dụng nguyên bản.
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
CẬP NHẬT:
Đối với những người muốn nó: Tôi nghĩ rằng nó an toàn để nói rằng hầu hết mọi người sử dụng khoảng cách levenshtein để tính toán tỷ lệ phần trăm trận đấu mờ. Đây là một cách để làm điều đó, và tôi đã thêm một tối ưu hóa mà bạn có thể chỉ định min. khớp% để trả về (mặc định là 70% +. Bạn nhập phần trăm như "50" hoặc "80" hoặc "0" để chạy công thức bất kể).
Tốc độ tăng lên đến từ thực tế là chức năng sẽ kiểm tra xem có thể là nó nằm trong tỷ lệ phần trăm bạn đưa ra bằng cách kiểm tra độ dài của 2 chuỗi. Xin lưu ý có một số lĩnh vực mà chức năng này có thể được tối ưu hóa, nhưng tôi đã giữ nó ở đây vì mục đích dễ đọc. Tôi nối khoảng cách trong kết quả cho bằng chứng về chức năng, nhưng bạn có thể fiddle với nó :)
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
Mã này cũng hoạt động kéo và thả cho Access VBA. :) – HelloW
Lưu ý nhanh cho người dùng trong tương lai, VBA 'Integer' tuyên bố * nên * sử dụng ít bộ nhớ hơn và nhanh hơn, nhưng giờ đây chúng được tự động chuyển thành loại' Long' phía sau hậu trường (nguồn: [MSDN] (https: // msdn .microsoft.com/vi-us/library/office/aa164506 (v = office.10) .aspx), xem [this] (http://stackoverflow.com/a/26409520/6609896)). Vì vậy, để tăng hiệu năng cận biên, hãy khai báo tất cả là 'Long' tiết kiệm thời gian chuyển đổi nội bộ (một số câu trả lời khác mà tôi thấy đã sử dụng điều này). HOẶC, nếu chuỗi của bạn có độ dài dưới 255 ký tự, hãy khai báo là 'Bytes' vì điều này yêu cầu bộ nhớ ít hơn' Integer'. – Greedo