當需要遍歷許多項目,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)
根據您的約束,(因爲排列是多餘的計算和空間明智的),你可以替換的組合排列,但那麼你的訪問方法將需要進行調整(因爲AB將只在上市[b]但不是b [a])。
在我使用quick_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: #arbitrary threshhold
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()'來代替。 – 2012-03-23 17:47:48
另外,你有什麼理由在這裏使用'SequenceMatcher'?也許你可以提供你自己的差異度量,這個度量可以針對你的問題進行優化,而不是訴諸像'quick_ratio'這樣看起來很差的函數。這將有助於理解問題的背景:每個字符串有多長,爲什麼它們很重要,如果它們相似,以何種方式定義相似性等等。 – 2012-03-23 18:03:08
請注意,'quick_ratio'比'比率... ... anagrams的比率尤其成問題。以「contains」和「sanction」爲例:'quick_ratio'爲'1.0',但'ratio'爲'0.375'。但它確實給出了一個上限,所以你可以同時使用它們 - 使用'quick_ratio'來快速消除明顯不同的字符串,然後在剩下的部分使用更昂貴的比率。顯然你會想要描述這個,最糟糕的情況是它可能會變慢。 – cha0site 2012-03-23 18:04:24