difflib.SequenceMatcher get_matching_blocks()的未解决行为

时间:2012-08-27 12:50:34

标签: python string fuzzy difflib

我正在试验fuzzywuzzy并遇到了很多情况,它产生了错误的结果。我尝试调试并遇到了一个难以解释的get_matching_blocks()场景。

我对get_matching_blocks()的理解是,它应该返回一个三元组元组(i,j,n),其中索引n的第一个字符串中长度为i的子字符串应完全匹配在索引j的第二个字符串中使用长度为n的子字符串。

>>> hay = """"Find longest matching block in a[alo:ahi] and b[blo:bhi]. If isjunk was omitted or None, find_longest_match() returns (i, j, k) such that a[i:i+k] is equal to b[j:j+k], where alo <= i <= i+k <= ahi and blo <= j <= j+k <= bhi. For all (i', j', k') meeting those conditions, the additional conditions k >= k', i <= i', and if i == i', j <= j' are also met. In other words, of all maximal matching blocks, return one that starts earliest in a, and of all those maximal matching blocks that start earliest in a, return the one that starts earliest in b."""
>>> needle = "meeting those conditions"
>>> needle in hay
True
>>> sm = difflib.SequenceMatcher(None,needle,hay)
>>> sm.get_matching_blocks()
[Match(a=5, b=8, size=2), Match(a=24, b=550, size=0)]
>>> 

那么为什么上面的代码找不到匹配的块?

1 个答案:

答案 0 :(得分:2)

我可能看不太清楚,但您不匹配hayneedle。你有

sm = difflib.SequenceMatcher(None,needle, sms)

不应该是

sm = difflib.SequenceMatcher(None, needle, hay)

?此外,对于记录,get_matching_blocks()返回的列表中的最后一个元素是格式的哑元(len(a),len(b),0)。

也许这只是在粘贴中的错误,但请用实际代码更新您的问题(我正在考虑SequenceMatcher()方法)


SequenceMatcher打破了“垃圾启发式” - 如果第二个字符串长度至少为200个字符,则垃圾是每个字母,其中(count-1)超过总数的1%长度。来自official bug ticket的评论(即this comment):

  

错误的原因是启发式:如果第二个序列是在   至少200项,然后任何项目超过百分之一   第二个序列中的时间被视为垃圾。这是为了   重复出现的代码行,如'else:'和'return',但可能是致命的   小字母表,其中常见项目是必要的内容。

我还将自己引用上述作者提供的代码示例:

这里len(a)== 200,len(b)== 199:

>>> print(SM(None, 'x' + 'y'*199, 'y'*199).ratio())
>>> 0.9975 #correct

这里len(a)== 199,len(b)== 200(我们切换ab):

>>> print(SM(None, 'y'*199, 'x' + 'y'*199).ratio())
>>> 0 #wrong

显然两种情况都应该给出相同的输出。

通过添加我提到的autojunk可选参数来修复 错误,其中 - 为了正确行为,应手动设置为False