2017-06-01 60 views
1

考慮這個例子:爲什麼fuzzywuzzy不考慮字符順序

>> from fuzzywuzzy import process 
>> choices = ['account', 'update', 'query'] 
>> process.extract('u', choices) 
[('account', 90), ('update', 90), ('query', 90)] 

在上述情況下,它混​​淆了我的最終用戶是帳戶排名上面更新對於給定的字符串。在這種情況下,帳戶由於列表順序而恰好被置於前面,因爲所有的比賽都有相同的得分。不過,我會想象更新會有更高的分數,只是因爲字符串中出現字符u

這是一個概念錯誤還是我沒有在這裏使用正確的得分手?

回答

1

首先你使用的是一個「壞」的得分手。根據你的分數你可能使用difflib。您應該切換到基於python-Levenshtein的實施。這可以通過參數scorer完成。

from fuzzywuzzy import process 
from fuzzywuzzy import fuzz 

def MyScorer(s1, s2): 
    fratio = fuzz.ratio(s1, s2) 
    fratio -= (s2.find(s1)*5) 
    return fratio 

choices = ['account', 'update', 'query'] 
dex = process.extract('u', choices, scorer=fuzz.token_sort_ratio) 
mex = process.extract('u', choices, scorer=MyScorer) 
print("Default Scorer:", dex) 
print("MyScorer:", mex) 

現在輸出

[('query', 33), ('update', 29), ('account', 25)]

哪個更好,但Levenshtein並沒有真正關心的位置,

Levenshtein距離(LD)是衡量兩個字符串之間的相似性,我們將其稱爲源字符串和目標字符串(t)。距離是將s轉換爲t所需的刪除,插入或替換的數量。

這就是爲什麼我添加了MyScorer()的定義,您可以在其中實現您自己的算法,將該位置考慮在內。我還添加了一個考慮位置的實現示例(但我沒有真正設計這些算法的經驗,所以不要指望這個算法是完美的或者甚至是可用的)。無論如何,MyScorer的輸出是:

[('update', 29), ('query', 28), ('account', 5)]

+0

感謝您的解釋。我很好奇 - 這不是大多數模糊搜索的自然行爲嗎?例如,在Sublime Text/Visual Studio Code中使用** CMD + SHIFT + P **並鍵入* u *將突出顯示命令中的* u *字符,但它總是以* u *開頭的命令顯示。 –

+0

我想他們要麼創建了自己的模糊匹配算法,要麼他們只是使用了不同的庫。 [fuzzyset](https://github.com/axiak/fuzzyset)開箱即可出色完成工作,你可能想嘗試一下。 (不要使用pip軟件包,它已經過時了!下載github軟件倉庫和easy_install軟件) – Skynet

0

「process.extract」在選擇的列表或字典中查找最佳匹配,返回包含匹配和它的分數的元組列表。它不依賴於列表或字典中選項的「位置」。

0

在您的代碼:

process.extract('u', choices) 

你不及格的得分手函數提取方法。該方法將爲您選擇4個足球的最大比例。

  • base_ratio:Levenshtein距離的兩個字符串。
  • partial_ratio:最相似子串的比例。
  • token_sort_ratio:在比較之前測量序列的相似性,對令牌進行排序。
  • token_set_ratio:查找每個字符串中的所有字母數字標記。

在你的情況,原點字符串是u,和目標串accountupdatequery
基本比例是account : 25,update : 29,query : 33
部分比例均爲90.
並且令牌分類比例和令牌設置比率均爲85.5。
所以每個字符串的最大比率是90.
所以你得到輸出[('account', 90), ('update', 90), ('query', 90)]

相關問題