为什么fuzzywuzzy不考虑字符顺序

时间:2017-06-01 05:24:13

标签: python fuzzy-search fuzzywuzzy

考虑这个例子:

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

在上述情况下,对于我的最终用户而言,帐户的排名高于给定字符串的 update ,这让我感到困惑。在这种情况下,由于列表顺序,帐户碰巧被任意放在前面,因为所有匹配都共享相同的分数。但是,我会想象 update 会有更高的分数,因为字符 u 会在字符串的前面显示。

这是一个概念错误,还是我没有在这里使用正确的得分手?

3 个答案:

答案 0 :(得分:3)

首先,你使用的是一名“糟糕”的得分手。根据您的分数,您可能正在使用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)]

答案 1 :(得分:1)

在您的代码中:

process.extract('u', choices)  

您没有将记分器功能传递给提取方法。该方法将选择4足球的最大比例。

  
      
  • base_ratio:两个字符串的Levenshtein距离。
  •   
  • partial_ratio:大多数相似子字符串的比率。
  •   
  • token_sort_ratio:衡量在比较之前对令牌进行排序的相似性。
  •   
  • token_set_ratio:查找每个字符串中的所有字母数字标记。
  •   

在您的情况下,原始字符串为u,目标字符串为accountupdatequery
基本比率为account : 25update : 29query : 33 部分比例均为90 令牌排序比率和令牌集合率均为85.5 所以每根弦的最大比例是90 所以你得到输出[('account', 90), ('update', 90), ('query', 90)]

答案 2 :(得分:0)

" process.extract"在列表或选项词典中找到最佳匹配,返回包含匹配及其得分的元组列表。它不依赖于"位置"列表或字典中的选择。