获取字典中多个单词的近似匹配项

时间:2017-06-29 21:10:00

标签: python string dictionary fuzzy-search

我有一个具有以下结构的字典:

{
    1: {"names": ["name1_A", "name1_B", ...]},
    2: {"names": ["name2_A", "name2_B", ...]},
    ...
}

其中name1_Aname1_B是同义词/别名/写同名的不同方式,其ID为1. name2_Aname2_B是同名的别名,其ID为2,依此类推。

我需要编写一个函数,该函数接受用户输入并返回其别名与用户输入最相似的名称的ID。

我知道理解我的意思并不是很直观,所以这是一个例子。让我们说这是我的字典:

{
    1: {"names": ["James", "Jamie"]},
    2: {"names": ["Karen", "Karyn"]}
}

用户输入单词Jimmy。由于与字典Jimmy的最接近匹配是Jamie,因此该函数必须返回ID 1。

如果用户输入世界Karena,由于最接近的匹配是Karen,因此该函数必须返回ID 2.

我认为获得最接近数学的最佳方法是使用difflibget_close_matches()。但是,该函数将可能性列表作为参数,我无法想到在函数中正确使用它的方法。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:4)

如果您对第三方模块感兴趣,那么我喜欢使用这个名为fuzzywuzzy的小模块,用于Python中的模糊字符串匹配。此模块使用Levenshtein Distance指标计算两个字符串之间的距离。以下是您如何使用它的示例:

>>> from fuzzywuzzy import fuzz
>>> from functools import partial
>>> data_dict = {
...     1: {"names": ["James", "Jamie"]},
...     2: {"names": ["Karen", "Karyn"]}
... }
>>> input_str = 'Karena'
>>> f = partial(fuzz.partial_ratio, input_str)
>>> matches = { k : max(data_dict[k]['names'], key=f) for k in data_dict}
>>> matches
{1: 'James', 2: 'Karen'}
>>> { i : (matches[i], f(matches[i])) for i in matches }
{1: ('James', 40), 2: ('Karen', 100)}

现在,您可以提取Karen,因为它的分数最高。

为了本演示的目的,我必须两次调用该函数,但您应该只能执行一次,具体取决于您对此示例的扩展方式。

另一点需要注意的是fuzz.partial_ratio对其匹配更宽松。对于更严格的匹配方案,请考虑使用fuzz.ratio

您可以使用模糊字符串匹配here来仔细阅读更多示例。