如何在python中使用相似度得分在大字符串中找到类似的子字符串?

时间:2018-01-05 16:24:30

标签: python string nlp distance similarity

我正在寻找的不仅仅是两个文本之间的简单相似性得分。但是字符串中子字符串的相似性得分。说:

text1

在上面的示例中,text2的所有单词都完全出现在text1中,因此相似度应为100%。

如果缺少std::vector<uchar>的某些单词,则分数应该更低。

我正在使用不同段落大小的大型数据集,因此在较大的段落中找到较小的段落具有这样的相似性得分是至关重要的。

我发现只有字符串相似性,例如余弦相似度,difflib相似性等,它们比较两个字符串。但不是关于另一个字符串中的子串的分数。

3 个答案:

答案 0 :(得分:4)

根据您的描述,如何:

>>> a = "cat is sleeping on the mat"
>>> b = "the cat is sleeping on the red mat in the living room"
>>> a = a.split(" ")
>>> score = 0.0
>>> for word in a: #for every word in your string
        if word in b: #if it is in your bigger string increase score
            score += 1
>>> score/len(a) #obtain percentage given total word number
1.0

如果它有一个遗漏的单词,例如:

>>> c = "the cat is not sleeping on the mat"
>>> c = c.split(" ")
>>> score = 0.0
>>> for w in c:
        if w in b:
            score +=1
>>> score/len(c)
0.875

此外,您可以按@roadrunner建议并拆分b并将其保存为一组,以便b = set(b.split(" "))加快您的效果。这会将该部分复杂度降低到O(1),并将整体算法提高到O(n)复杂度。

编辑:你说你已经尝试了一些像Cosine Similarity等指标。但是我怀疑你可能会从检查Levenshtein Distance相似性中受益,我怀疑这可能会对此有所帮助案例作为所提供解决方案的补充。

答案 1 :(得分:4)

您还可以使用collections.defaultdict来存储word_a中存在的word_b中的字数,然后sum()计算word_a的长度from collections import defaultdict a = "the cat is not sleeping on the mat" b = "the cat is sleeping on the red mat in the living room" word_a = a.split() word_b = set(b.split()) d = defaultdict(int) for word in word_a: if word in word_b: d[word] += 1 print(sum(d.values()) / len(word_a)) 最后:

0.875

哪个输出:

word_a

注意:由于我们只关心检查word_b中是否存在word_b中的字词,因此将set()转换为O(1)将允许O(n)查找,而不是保持列表,O(n)。然后,这使得上述代码import { Pusher } from 'pusher-js'; 的总时间复杂度成为可能。

答案 2 :(得分:2)

与DarkCygbus类似,但相似性基于其计数总字符而非单词。另一方面,此脚本仅检查与完整单词(text_2.split())

的重合
from __future__ import division

text_1 = 'cat is sleeping on the mat'
text_2 = 'The cat is sleeping on the red mat in the living room'
no_match = 0
match = 0

for word in text_1.split():
    if word not in text_2.split():
        no_match += len(word)
    else:
        match += len(word)

similarity = match/(match + no_match)
print ('{0:.0%}'.format(similarity))