0

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

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

>>> 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)]
>>> 

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

4

1 回答 1

2

我可能看不太清楚,但你不匹配hayand needle。你得到了

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

不应该

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

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

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


SequenceMatcher破坏了“垃圾启发式” - 如果第二个字符串至少有 200 个字符长,则每个字母(计数 1)超过总长度的 1% 就是垃圾。来自官方 bug 票的评论(即此评论):

该错误的原因是启发式的:如果第二个序列的长度至少为 200 个项目,那么在第二个序列中出现超过 1% 的时间的任何项目都被视为垃圾。这是针对像“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.

于 2012-08-27T13:09:24.600 回答