2014-01-10 117 views
3

我有兩個列表list1list2。我在stackoverflow上找到了一個非常簡單的方法來獲取這兩個列表中的常見元素,如下所示result = list(set(list1) & set(list2))。不幸的是,由此,結果列表中元素的順序不會被保留。兩個列表之間的共同元素和保留兩個列表中元素的順序

例如:

list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

我想要的結果(共同要素)是這一順序['e', 'a', 'b', 'c']。因爲,例如,'e'在list1和list2中,並且在list1中位於2並且在list2中位於1,而'a'在list1和list2中,並且在list1中位於1並且在list2中位於位置3,因此'e'在2之前是'a'1 + 3。

那麼,是否有任何簡單的方法來使兩個列表之間具有共同元素並保留元素的順序?

+0

你想假設「e」和「T」在List1被換什麼順序? – wim

+0

'list1 = ['a','b']的預期輸出是什麼? list2中= [ 'B', 'A']'?按照你的算法,'a'和'b'具有相同的位置值'3',所以首先呢? – Kevin

+0

@Kevin在這種情況下無關緊要如果結果是[a,b]或[b,a] – shn

回答

4
list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

weights = defaultdict(int) 

for i, e in enumerate(list1): 
    weights[e] += i 

for i, e in enumerate(list2): 
    weights[e] += i 

>>> result = sorted(set(list1) & set(list2), key=lambda i: weights[i]) 
>>> result 
['e', 'a', 'b', 'c'] 
2

你可以使用列表解析來過濾從list1所有元素不也屬於list2

list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

result = [item for item in list1 if item in list2] 
print result 

結果:

['a', 'e', 'b', 'c'] 

雖然這不符合預期的結果在你的主帖中,從你的後續評論看來,這似乎是一個可以接受的結果。


你也可以繼續使用一套方法,然後使用您所描述的定位算法在事後對結果進行排序:

list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

items = set(list1) & set(list2) 
result = sorted(items, key=lambda element: list1.index(element) + list2.index(element)) 

print result 

結果:

['e', 'a', 'b', 'c'] 
1

時,可以保留像這樣的一個清單的順序,通過僅使其中的一個成爲一組:

list1 = ['a', 'e', 't', 'b', 'c'] 
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

slist1 = set(list1) 
slist2 = set(list2) 

# list1 determines the ordering 
olist1 = [x for x in list1 if x in slist2] 

# list2 determines the ordering 
olist2 = [x for x in list2 if x in slist1] 

基本上,你遍歷一個列表,並檢查每個項目,看看它是否在另一個。這可確保您的最終列表與原始列表的順序相同,而且它只包含兩個列表中的條目。

使用套件大大加速了包含檢查。

如果您想做比這更復雜的任何事情(例如,最終排序依賴於兩個列表中的索引),那麼您需要更詳細地瞭解這些詳細信息。

編輯:好的,你確實發佈了更多關於你想要做什麼的細節。 不知道它是最快,但你可以做這樣的事情來獲得指標:

list1_offsets = dict(x[::-1] for x in enumerate(list1)) 
list2_offsets = dict(x[::-1] for x in enumerate(list2)) 

total_list = slist1 & slist2 

total_offset = [(x, list1_offsets[x] + list2_offsets[x]) for x in total_list] 

final_list = [x[0] for x in sorted(total_offset, key=itemgetter(1))] 

在這種情況下,產量的預期['e', 'a', 'b', 'c']

+0

這將刪除單例,但它也會刪除重複的信息... –

+0

已修改...但另一個答案是一樣的,但現在還有另一個更短的答案。可能會很快刪除。 –

0

您的訂購功能似乎很奇怪,但確定。您需要找到交叉點並基本上通過訂購功能對其進行分類。

order_function = lambda val: list1.index(val) + list2.index(val) 
common = set(list1) & set(list2) 
indexed = [(order_function(v), v) for v in common] 
return [x[1] for x in sorted(indexed)] 
相關問題