[英]What is a simple fuzzy string matching algorithm in Python?
我试图找到某种好的、模糊的字符串匹配算法。 直接匹配对我不起作用——这不太好,因为除非我的字符串 100% 相似,否则匹配失败。 Levenshtein方法不适用于字符串,因为它适用于字符级别。 我一直在寻找类似词级匹配的东西,例如
字符串 A:快速的棕色狐狸。
字符串B:敏捷的棕色狐狸跳过了懒惰的狗。
这些应该匹配,因为字符串 A 中的所有单词都在字符串 B 中。
现在,这是一个过于简单的例子,但有谁知道一个在单词级别上工作的好的模糊字符串匹配算法。
我喜欢德鲁的回答。
您可以使用difflib查找最长匹配项:
>>> a = 'The quick brown fox.'
>>> b = 'The quick brown fox jumped over the lazy dog.'
>>> import difflib
>>> s = difflib.SequenceMatcher(None, a, b)
>>> s.find_longest_match(0,len(a),0,len(b))
Match(a=0, b=0, size=19) # returns NamedTuple (new in v2.6)
或者选择一些最小匹配阈值。 例子:
>>> difflib.SequenceMatcher(None, a, b).ratio()
0.61538461538461542
看看 SeatGeek 昨天开源的这个 python 库。 显然,大多数这类问题都非常依赖于上下文,但它可能对您有所帮助。
from fuzzywuzzy import fuzz
s1 = "the quick brown fox"
s2 = "the quick brown fox jumped over the lazy dog"
s3 = "the fast fox jumped over the hard-working dog"
fuzz.partial_ratio(s1, s2)
> 100
fuzz.token_set_ratio(s2, s3)
> 73
如果您只想测试一个字符串中的所有单词是否与另一个字符串匹配,那就是一个单行:
if not [word for word in b.split(' ') if word not in a.split(' ')]:
print 'Match!'
如果你想给它们打分而不是二进制测试,为什么不做这样的事情:
((匹配单词的数量) / (较大字符串中的单词数量)) * ((较小字符串中的单词数量) / (较大字符串中的单词数量))
?
如果你愿意,你可以变得更有趣,并对每个字符串进行模糊匹配。
你可以试试这个 python 包,它使用机器学习的模糊名称匹配。
pip install hmni
初始化匹配器对象
import hmni
matcher = hmni.Matcher(model='latin')
单对相似度
matcher.similarity('Alan', 'Al')
# 0.6838303319889133
matcher.similarity('Alan', 'Al', prob=False)
# 1
matcher.similarity('Alan Turing', 'Al Turing', surname_first=False)
# 0.6838303319889133
注意:我还没有构建这个包。 在这里分享它,因为它对我的使用非常有用。 GitHub
您可以修改 Levenshtein 算法来比较单词而不是字符。 这不是一个非常复杂的算法,并且可以在线获得多种语言的源代码。
Levenshtein 通过比较两个字符数组来工作。 没有理由不能对两个字符串数组应用相同的逻辑。
前段时间我用 C# 做了这个,我以前的问题在这里。 有您感兴趣的入门算法,您可以轻松地将其转换为 python。
您应该使用编写自己的算法的想法是这样的:
- 有一个带有原始“标题”的列表(要与之匹配的单词/句子)。
- 每个标题项都应该在单词/句子上有最低的匹配分数,也忽略标题。
- 您还应该拥有最终结果的全局最小匹配百分比。
- 您应该计算每个单词 - 单词 Levenshtein 的距离。
- 如果单词按相同顺序排列,您应该增加总匹配权重(quick brown vs quick brown,应该比 quick brown vs. brown quick 具有更高的权重。)
您可以从https://github.com/frazenshtein/fastcd/blob/master/search.py尝试 FuzzySearchEngine。
这种模糊搜索仅支持单词搜索,并且该单词具有固定的容许误差(仅对两个相邻字符进行一次替换或换位)。
但是,例如,您可以尝试以下操作:
import search
string = "Chapter I. The quick brown fox jumped over the lazy dog."
substr = "the qiuck broqn fox."
def fuzzy_search_for_sentences(substr, string):
start = None
pos = 0
for word in substr.split(" "):
if not word:
continue
match = search.FuzzySearchEngine(word).search(string, pos=pos)
if not match:
return None
if start is None:
start = match.start()
pos = match.end()
return start
print(fuzzy_search_for_sentences(substr, string))
11 将被打印
如果您比较单词(由停止字符序列分隔的字符串)而不是单个字母,Levenshtein 应该可以正常工作。
def ld(s1, s2): # Levenshtein Distance
len1 = len(s1)+1
len2 = len(s2)+1
lt = [[0 for i2 in range(len2)] for i1 in range(len1)] # lt - levenshtein_table
lt[0] = list(range(len2))
i = 0
for l in lt:
l[0] = i
i += 1
for i1 in range(1, len1):
for i2 in range(1, len2):
if s1[i1-1] == s2[i2-1]:
v = 0
else:
v = 1
lt[i1][i2] = min(lt[i1][i2-1]+1, lt[i1-1][i2]+1, lt[i1-1][i2-1]+v)
return lt[-1][-1]
str1 = "The quick brown fox"
str2 = "The quick brown fox jumped over the lazy dog"
print("{} words need to be added, deleted or replaced to convert string 1 into string 2".format(ld(str1.split(),str2.split())))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.