当需要遍历许多项时,itertools应运而生!
以下代码段可以将您的字符串的所有可能排列(排列)进行排列,并以您原始代码的方式返回它们。 我认为使用 not in
的方式是一种不必要昂贵的检查方式,也不够pythonic。选择排列是因为它可以使您最方便地检查给定两个字符串 a->b 或 b->a 之间的关系。
import difflib
import itertools
def diff(a, b):
return difflib.SequenceMatcher(None, a, b).quick_ratio()
def calculate_ratios(strings):
dupl = dict()
for s, t in itertools.permutations(strings, 2):
try:
dupl[s].append({t: diff(s,t)})
except KeyError:
dupl[s] = []
dupl[s].append({t: diff(s,t)})
return dupl
a = ['first string', 'second string', 'third string', 'fourth string']
print calculate_ratios(a)
根据您的限制(因为排列在计算和空间方面是冗余的),您可以用组合替换排列,但是访问方法需要进行调整(因为a-b只会在a[b]中列出,而不是b[a])。
在代码中我使用了quick_ratio(),但是根据您是否需要足够的精度,它可以简单地更改为ratio()或real_quick_ratio()。
在这种情况下,一个简单的IF语句就可以解决这个问题:
import difflib
import itertools
def diff(a, b):
return difflib.SequenceMatcher(None, a, b).quick_ratio()
def diff2(a, b):
return difflib.SequenceMatcher(None, a, b).ratio()
def calculate_ratios(strings, threshold):
dupl = dict()
for s, t in itertools.permutations(strings, 2):
if diff(s,t) > threshold:
try:
dupl[s].append({t: diff2(s,t)})
except KeyError:
dupl[s] = []
dupl[s].append({t: diff2(s,t)})
return dupl
a = ['first string', 'second string', 'third string', 'fourth string']
print calculate_ratios(a, 0.5)
SequenceMatcher.ratio()
的计算成本相当高,因此你可以尝试使用quick_ratio()
或者甚至是real_quick_ratio()
来代替。 - Niklas B.SequenceMatcher
有什么原因吗?也许你可以提供自己的差异度量标准,这将针对你的问题进行优化,而不是诉诸于一个似乎文档不太好的函数quick_ratio
。了解你的问题的背景会有所帮助:每个字符串有多长,如果它们相似很重要,你想如何定义相似性等等。 - machine yearningquick_ratio
比ratio
差得多... 乱序词比率尤其令人困扰。以 "contains" 和 "sanction" 为例:quick_ratio
是1.0
,但是ratio
只有0.375
。但它确实提供了一个上限,所以你可以两者都使用——使用quick_ratio
快速排除明显不同的字符串,然后在剩下的内容上使用更昂贵的ratio
。显然您需要对此进行分析,最坏情况下会更慢。 - cha0sitequick_ratio
和real_quick_ratio
。首先使用它们是个好主意。我认为另一个问题是迭代18000个元素的列表。有更快的迭代方法吗? - annndrey