Python中的字符串相似性

时间:2016-03-27 21:25:44

标签: python string-comparison

我正在尝试在Python中对字符串进行比较。我的字符串包含可以通过多种不同方式构建的标题:

'Title'
'Title: Subtitle'
'Title - Subtitle'
'Title, Subtitle'
'Title Subtitle'

是否可以在Python中进行相似性比较,以便它可以确定match('Title: Subtitle', 'Title - Subtitle') = True? (或者它会被构造)

基本上我正在试图确定它们是否是相同的标题,即使分裂是不同的。

if 'Title: Subtitle' == 'Title - Subtitle':
    match = 'True'
else:
    match = 'False'

还有一些可能会存储为The Title: The SubtitleTitle, The: Subtitle, The,但我认为这可能会增加一些复杂性,我可能会通过重建字符串来解决这个问题。

8 个答案:

答案 0 :(得分:10)

您正在尝试做的事情已经在jellyfish包中很好地实现了。

>>> import jellyfish
>>> jellyfish.levenshtein_distance('jellyfish', 'smellyfish')
2

答案 1 :(得分:6)

标准库的difflib模块提供了一个函数get_close_matches,它可以进行模糊字符串匹配。

>>> import difflib
>>> difflib.get_close_matches('python', ['snakes', 'thon.py', 'pythin'])
['pythin', 'thon.py']  # ordered by similarity score

答案 2 :(得分:3)

您可以使用in关键字。这不是相似性比较,而是做你想要的:

s = "Title: Subtitle"

if "Title" in s or "Subtitle" in s:
    match = 'True'
else:
    match = 'False'

答案 3 :(得分:2)

尝试替换字符,然后检查相等性:

def match(str1, str2):
    str1 = str1.replace(' -', '').replace(',', '').replace(':', '')
    str2 = str2.replace(' -', '').replace(',', '').replace(':', '')
    return str1 == str2
>>> match('Title: Subtitle', 'Title - Subtitle')
True
>>> match('Title: Subtitle', 'Title, Subtitle')
True
>>> 

答案 4 :(得分:2)

如果唯一的障碍是标点符号,则问题很简单:只需丢弃非单词字符并比较剩余的单词列表。

s1 = 'Title - Subtitle'
toks1 = re.split(r"^\W+", s1)  # keep just the words
toks1 = [ w.lower() for w in toks1 ]

我投入了小套房,因为这也可能有所不同。将相同的内容应用于每个输入并比较列表。

但正如你所指出的那样,可能存在其他差异。如果您的数据真的包含标题(书籍,电影,科学文章),您可以从库中删除文章和常用连词(所谓的“停用词”)开始。例如,“文章标题”被删除为["title", "article"]。为了处理单词顺序中的其他可能的差异,您可以使用所谓的“词袋”方法,在信息检索中很常见。将标记列表转换为集合,或转换为单词计数字典,以用于多次出现某些单词的情况。以下是一个示例,使用单词计数和nltk的“停用词”列表作为过滤器。

import nltk
from collections import Counter
stopwords = set(nltk.corpus.stopwords.words("english"))

toks1 = [ t for t in toks1 if t not in stopwords ]
cnt1 = Counter(toks1)
cnt2 = Counter(toks2)  # Another title string, processed the same way
if cnt1 == cnt2:
    print("The two strings have exactly the same content words")

如果还有更多变化,天空就是极限。近似文本匹配是活跃研究的主题,应用于信息检索,抄袭检测,遗传学等。您可以检查一个标题是否是另一个的子集(可能有人遗漏了副标题)。您可以尝试通过“编辑距离”进行匹配(例如,由其他几个答案提到的“Levenshtein距离”),将其应用于字母或整个单词。您可以尝试TF-IDF评分等信息检索算法。这些只是您可以尝试的一些事项,因此请寻找能够为您完成工作的最简单的解决方案。谷歌是你的朋友。

答案 5 :(得分:1)

我是一名Ruby程序员,因此没有使用Python的经验,但在Ruby中,使用gem Levensthein可以很快解决这个问题。它计算您需要对字符串进行编辑的次数,以获得相同的字符串。

我也看到了Python的等价物,所以看看https://pypi.python.org/pypi/python-Levenshtein

答案 6 :(得分:1)

这应该有效。 Python翻译可以用来取出任何不同的字符。

valid mathematical expressions

答案 7 :(得分:0)

fnmatch.fnmatch虽然是为Unix文件名匹配而设计的,但也可以使用,请考虑以下示例:

>>> from fnmatch import fnmatch
>>> l
['Title: Subtitle', 'Title - Subtitle', 'Title, Subtitle', 'Title Subtitle']
>>>
>>> all(fnmatch(x, 'Title*Subtitle') for x in l)
True

另一种方法是检查它们是否都匹配re模式:

>>> import re
>>> l
['Title: Subtitle', 'Title - Subtitle', 'Title, Subtitle', 'Title Subtitle']
>>> all(re.search(r'^Title.*?Subtitle$', x) for x in l)
True