我喜欢 Niklas R 的 the answer,但它有一个问题(取决于您的期望)。将答案与以下两个测试用例一起使用:
print compare('berry','peach')
print compare('berry','cherry')
我们可以合理地预期 cherry 更类似于 berry 而不是 peach。然而,berry 和 peach 之间的差异较小,然后是 berry 和 cherry:
(' | ', 4) # berry, peach
(' | ', 5) # berry, cherry
当字符串向后而不是向前时,会发生这种情况。为了从 Niklas R 的答案中扩展答案,我们可以添加一个帮助函数,它返回正常(正向)差异和反向字符串的差异之间的最小差异:
def fuzzy_compare(string1, string2):
(fwd_result, fwd_diff) = compare(string1, string2)
(rev_result, rev_diff) = compare(string1[::-1], string2[::-1])
diff = min(fwd_diff, rev_diff)
return diff
再次使用以下测试用例:
print fuzzy_compare('berry','peach')
print fuzzy_compare('berry','cherry')
...我们得到了
4 # berry, peach
2 # berry, cherry
正如我所说,这实际上只是扩展,而不是修改 Niklas R 的答案。
如果您只是在寻找一个简单的 diff 函数(考虑到前面提到的问题),则可以使用以下方法:
def diff(a, b):
delta = do_diff(a, b)
delta_rev = do_diff(a[::-1], b[::-1])
return min(delta, delta_rev)
def do_diff(a,b):
delta = 0
i = 0
while i < len(a) and i < len(b):
delta += a[i] != b[i]
i += 1
delta += len(a[i:]) + len(b[i:])
return delta
测试用例:
print diff('berry','peach')
print diff('berry','cherry')
在处理不同长度的单词时,最后一个考虑因素是 diff 函数本身。有两种选择:
- 将长度之间的差异视为差异字符。
- 忽略长度差异,只比较最短的单词。
例如:
-
apple 和 apples 在考虑所有情况时相差 1
人物。
-
apple 和 apples 相差 0 时
只考虑最短的单词
当只考虑我们可以使用的最短单词时:
def do_diff_shortest(a,b):
delta, i = 0, 0
if len(a) > len(b):
a, b = b, a
for i in range(len(a)):
delta += a[i] != b[i]
return delta
...迭代次数由最短的单词决定,其他的都被忽略。或者我们可以考虑不同的长度:
def do_diff_both(a, b):
delta, i = 0, 0
while i < len(a) and i < len(b):
delta += a[i] != b[i]
i += 1
delta += len(a[i:]) + len(b[i:])
return delta
在这个例子中,所有剩余的字符都被计算并添加到 diff 值中。测试这两个功能
print do_diff_shortest('apple','apples')
print do_diff_both('apple','apples')
将输出:
0 # Ignore extra characters belonging to longest word.
1 # Consider extra characters.