【问题标题】:Fuzzy Match values to list of list python模糊匹配值到列表 python
【发布时间】:2022-12-24 21:03:46
【问题描述】:

挣扎于如何以 pythonic 方式执行此操作。我有一个我们可以称之为名字的列表

[('Jimmy', 'Smith'), ('James', 'Wilson'), ('Hugh' "Laurie')]

然后我有两个变量

First_name = 'Jimm'

Last_name = 'Smitn'

我想遍历这个列表列表,名字和姓氏模糊匹配这些值并返回最接近指定的 First_name 和 Last_name 的列表

【问题讨论】:

  • 看看difflib.SequenceMatchermax(lst, key=lambda x: SequenceMatcher(None, " ".join(x), " ".join((First_name, Last_name))).ratio())
  • 效果很好!谢谢@OlvinR​​oght!如果你把它放在一个答案中,我会很乐意赞成它
  • 模糊匹配不是一个明确定义的概念。如果你不想拿出自己的,精确的告诉你某事是否匹配的规则,那么你将不得不使用内置假设的第三方库。在第一种情况下,问题没有正确聚焦,否则它会要求第三方库建议。无论哪种方式,问题都不是 Stack Overflow 上的 on topic

标签: python fuzzy


【解决方案1】:

您可以实施模糊匹配以获得最佳匹配率(使用max()difflib.SequenceMatcher() 返回。

要实现这一点,我们应该将 lambda 作为 key 参数传递,这将返回匹配率。在我的示例中,我将使用SequenceMatcher.ratio(),但如果性能很重要,您还应该尝试使用SequenceMatcher.quick_ratio()SequenceMatcher.real_quick_ratio()

from difflib import SequenceMatcher

lst = [('Jimmy', 'Smith'), ('James', 'Wilson'), ('Hugh', 'Laurie')]
first_name = 'Jimm'
last_name = 'Smitn'

matcher = SequenceMatcher(a=first_name + ' ' + last_name)
match_first_name, match_last_name = max(lst,
    key=lambda x: matcher.set_seq2(' '.join(x)) or matcher.ratio())

print(first_name, last_name, '-', match_first_name, match_last_name)

【讨论】:

  • 我正在更改此功能以过滤掉小于 n 的匹配项(例如 90)。这就是我所拥有的,但它似乎没有返回我想要的
  • matches = filter(lambda x: SequenceMatcher(None, " ".join(x), " ".join((First_Name, Last_Name))).ratio() > .90, lst)
  • @ChessGuy,您可以使用简单的列表理解([i for i in lst if matcher.set_seq2(' '.join(i)) or matcher.ratio() > 0.9])或申请filter()(list(filter(lambda l: matcher.set_seq2(' '.join(l)) or matcher.ratio() > 0.9, lst))).
【解决方案2】:

另一种可能的路径是使用集合交叉点。

names = [('Jimmy', 'Smith'), ('James', 'Wilson'), ('Hugh', 'Laurie')]
first_name = "Jimm"
last_name = "Smitn"

setf = set(first_name)
# {'m', 'i', 'J'}
setl = set(last_name)
# {'t', 'n', 'm', 'i', 'S'}

ranked = [(len(setf & set(f)) + len(setl & set(l)), f, l) for f, l in names]
# [(7, 'Jimmy', 'Smith'), (4, 'James', 'Wilson'), (1, 'Hugh', 'Laurie')]

best_match = max(ranked, key=lambda x: x[0])[1:]
# ('Jimmy', 'Smith')

【讨论】:

  • 很好的实施。您可以省略key 参数,python 使用字典顺序,因此默认情况下将比较第一项。您也可以使用 setf.intersection(f)setl.intersection(l) ,它们应该稍微快一些。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多