2017-06-21 62 views
0

我有2個列表。實際和預測。 我需要比較兩個列表並確定模糊匹配的數量。我說模糊匹配的原因是因爲它們不會完全相同。我正在使用difflib庫中的SequenceMatcher。Python - 匹配2個列表中的字符串

def similar(a, b): 
    return SequenceMatcher(None, a, b).ratio() 

我可以認爲,百分比匹配高於80%的字符串被認爲是相同的。示例列表

actual=[ "Appl", "Orange", "Ornge", "Peace"] 
predicted=["Red", "Apple", "Green", "Peace", "Orange"] 

我需要一種方法來挑選在實際列表中找到預測列表中的Apple,Peace和Orange。所以只有3場比賽,而不是5場比賽。 我該如何有效地做到這一點?

+3

問題是什麼? –

回答

2

您可以使用下面的一組修真使用similar方法以獲得所需的輸出,如果模糊匹配就是你要找確實是對於。

threshold = 0.8 
result = {x for x in predicted for y in actual if similar(x, y) > threshold} 
0
>>> actual=["Apple", "Appl", "Orange", "Ornge", "Peace"] 
>>> predicted=["Red", "Apple", "Green", "Peace", "Orange"] 
>>> set(actual) & set(predicted) 
set(['Orange', 'Peace', 'Apple']) 
1

您可以將兩個列表都設置爲集合並對它們應用交集。

這會給你三項{'Peace', 'Apple', 'Orange'}

比,你可以計算結果集len內的比率len到實際列表len。

actual=["Apple", "Appl", "Orange", "Ornge", "Peace"] 
predicted=["Red", "Apple", "Green", "Peace", "Orange"] 

res = set(actual).intersection(predicted) 

print (res) 
print ((len(res)/len(actual)) * 100) 

編輯:

爲了使用,您將需要實現嵌套循環的比率。 由於集合被實現爲散列表,所以搜索是O(1),我寧願使用實際的集合。

如果預測值處於實際(完全匹配)中,那麼只需將其添加到結果集中即可。 (最好的情況是,所有這些和最終的複雜性是O(n))。

如果預測結果不是實際的,則通過實際循環並查找是否存在超過0.8的比率。 (最壞的情況是,所有的都是這樣的,複雜性(在^ 2))

actual={"Appl", "Orange", "Ornge", "Peace"} 
predicted=["Red", "Apple", "Green", "Peace", "Orange"] 

result = {} 

for pre in predicted: 
    if pre in actual: 
     result.add(pre) 
    else: 
     for act in actual: 
      if (similar(pre, act) > 0.8): 
       result.add(pre) 
+0

這種方法不會考慮模糊匹配。我已經改變了名單,現在即使Appl和Apple共享88%的比賽,「Apple」也不會被識別。 –

+0

@JavaBeginner,增加了一個編輯部分。 –

0

我這種情況下,你只需要檢查預測列表中的元素是否存在於實際列表中。 如果存在,則添加到新列表。

In [2]: actual=["Apple", "Appl", "Orange", "Ornge", "Peace"] 
...: predicted=["Red", "Apple", "Green", "Peace", "Orange"] 


In [3]: [i for i in predicted if i in actual] 
Out[3]: ['Apple', 'Peace', 'Orange'] 
0

簡單的辦法,但效果不理想,將是:

counter = 0 
for item in b: 
    if SequenceMatcher(None, a, item).ratio() > 0: 
     counter += 1 

這是你想要的,模糊匹配的元素,不僅有相同的元素(如大多數其他的答案提供)數量。

1
{x[1] for x in itertools.product(actual, predicted) if similar(*x) > 0.80} 
0

先取兩個集合的交集:

actual, predicted = set(actual), set(predicted) 

exact = actual.intersection(predicted) 

如果這包括所有實際的話,那麼你就大功告成了。然而,

if len(exact) < len(actual): 
    fuzzy = [word for word in actual-predicted for match in predicted if similar(word, match)>0.8] 

最後的結果集是exact.union(set(fuzzy))

0

您還可以試試下面的方法來實現您的要求:

import itertools 

fuzlist = [ "Appl", "Orange", "Ornge", "Peace"] 
actlist = ["Red", "Apple", "Green", "Peace", "Orange"] 
foundlist = [] 
for fuzname in fuzlist: 
    for name in actlist: 
     for actname in itertools.permutations(name): 
      if fuzname.lower() in ''.join(actname).lower(): 
       foundlist.append(name) 
       break 

print set(foundlist)