我试图将具有简短描述的对象链接到另一个具有其他更长描述的对象,例如:
short_string = "fo r ba oo"
long_string1 = "foo bar baz"
long_string2 = "soo az bn"
(这里的“long_strings”并不比我们的短片长,但这只是一个例子)。
我的目标是检查每个长字符串,它们为n-gram“覆盖”了多少短字符串(为了我们的示例,我们将采用n = 2),即短字符串找到的比例一个或多个匹配超过给定长字符串中的2个元素。
我们的比赛应该是(但不需要显示):
# match between short and long_string1
match1 = ['fo', 'ba', 'oo']
# same for long_string2
match2 = ['oo']
我们的输出将是长字符串中匹配的短字符串的比例:
# It would be better if we ignore the spaces
prop_match1 = sum([len(i) for i in match1])/len(short_string)
# 0.6
# same for prop_match2
# outputs 0.2
现在我正在使用difflib库中的SequenceMatcher,但这有几个问题:
查找最长匹配,然后拆分字符串以递归地比较每一方,即如果我们的最长匹配在中间并且在开头有一个“foo”在一个字符串和另一个字符串的末尾,它将不会被看到,例如:
“foo barr baz”和“baz barr foo”,只有“barr”匹配才能找到最长的匹配,SequenceMatcher将比较[“foo”,“baz”]一方和[“baz” “,”foo“]在另一方面。
真的很慢!我需要为每个长字符串比较几个小字符串,并根据总覆盖率找到最佳长字符串,并为数千个候选字符串执行此操作。再次从文档字符串中,当我看到线性的东西时,SequenceMatcher的成本介于二次和线性之间(这就是为什么我看一下后缀树,它看起来对字符串搜索有效,但我看不出它是怎么回事会帮助我解决问题,也不会在Python3中找到正确的实现。)
欢迎提供任何帮助,无论是我自己实现的简单算法还是可以修复我的问题的库!
编辑:使用SequenceMatcher
添加我的代码 for long_string in list_long_strings:
# Short formatting of the strings
long = long_string.upper().replace('\n', ' ')
matcher = difflib.SequenceMatcher(lambda x: x == ' ', long, '')
coverage_total = 0
for s in short_string_list:
matcher.set_seq2(s)
for block in matcher.get_matching_blocks():
if block[2] >= 2 : # Only matches with lenght 2 characters or more
coverage_total += block[2]