2012-08-27 63 views
0

我正在試驗fuzzywuzzy,並且在很多情況下遇到了錯誤的結果。我試圖調試並遇到get_matching_blocks()這個很難解釋的場景。未使用difflib.SequenceMatcher的行爲get_matching_blocks()

我get_matching_blocks(),則它應該返回三重元組的理解(I,J,n),其中的第一串中長度n的在索引i子串應與長度的子串完全匹配n在索引j的第二個字符串中。

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

SO爲什麼上面的代碼無法找到匹配的塊?

回答

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)註釋:

的原因bug是啓發式:如果第二序列的長度爲 至少200個項目長然後,在第二序列中發生的 超過百分之一的時間的任何項被視爲垃圾。這是針對 重複的代碼行,如'else:'和'return',但對於 小字母可能是致命的,其中常見項目是必需的內容。

我還將讓自己通過上述作者提供報價的代碼示例:

這裏LEN(一)== 200,LEN(B)== 199:

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

這裏len個(一)== 199,LEN(b)== 200(我們切換ab):

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

凡明顯這兩種情況下應給予相同的輸出。

的錯誤是固定通過添加可選的參數,我提到,autojunk,其中 - 在這裏正確的行爲 - 應手動設置爲False

+0

感謝您指出。我已經更新了這個問題。而且我知道這個事實,返回列表中的最後一個元素是一個虛擬的 – Abhijit

+2

好吧,我的壞,在解釋器中運行它會得到相同的結果。然而,切換參數產生正確的輸出,也許這會指向某人回答 – wasyl

+1

好的,另一個更新:這與'autojunk'參數有關。添加'False'作爲'SequenceMatcher'的第四個參數使得輸出正確 – wasyl