2016-12-13 212 views
17

我正在處理列表,我需要對它們進行比較以創建特定元素的新列表。例如:Python在一個列表中查找不在另一個列表中的元素

main_list=[] 
list_1=["a", "b", "c", "d", "e"] 
list_2=["a", "f", "c", "m"] 

我需要cicle上LIST_1並就main_list追加= []所有不list_2匹配的元素。

結果應該是這樣的:

main_list=["f", "m"] 

我如何與Python做呢?

+1

你尋找'list_2'無處出現在'list_1'或元素的元素在'list_2'中,它們不存在於'list_1'中的相同索引處? –

回答

8

(1)您可以使用NumPy的setdiff1d。從response of Chinny84,如果你關心的是獨特元素,那麼:

import numpy as np 
list_1 = ["a", "b", "c", "d", "e"] 
list_2 = ["a", "f", "c", "m"] 
main_list = np.setdiff1d(list_2,list_1) 

(2)否則,使用main_list = np.setdiff1d(list_2,list_1, assume_unique=True)

兩個答案會給你["f", "m"]。然而,如果list_2 = ["a", "f", "c", "m", "m"],答案(1)產生["f", "m"]但答案(2)給出["f", "m", "m"](因爲list_2中每個元素的唯一性並不重要)。

1

我會zip列表一起按元素逐一比較它們。

main_list = [b for a, b in zip(list1, list2) if a!= b] 
+0

如果OP想要逐元素比較(現在還不清楚,這個例子可能會變成任何一種方式),這比其他答案更有效率,因爲它是一個單一的「列表」單個新列表'正在建造,沒有額外的臨時工,沒有昂貴的收容檢查等。 – ShadowRanger

+0

@ShadowRanger這將只適用於元素方面的差異,這是一個關鍵點 –

+0

@fordprefect:Yup。 [我自己的回答](https://stackoverflow.com/a/41126821/364696)涵蓋了與位置無關的差異。 – ShadowRanger

34

您可以使用集:

main_list = list(set(list_2) - set(list_1)) 

輸出:

>>> list_1=["a", "b", "c", "d", "e"] 
>>> list_2=["a", "f", "c", "m"] 
>>> set(list_2) - set(list_1) 
set(['m', 'f']) 
>>> list(set(list_2) - set(list_1)) 
['m', 'f'] 

每@JonClements'評論,這裏是一個整潔的版本:

>>> list_1=["a", "b", "c", "d", "e"] 
>>> list_2=["a", "f", "c", "m"] 
>>> list(set(list_2).difference(list_1)) 
['m', 'f'] 
+0

如果我們只關心「獨特」元素,但如果我們有多個'm's',例如這樣就不會提取它,這很好。 – Chinny84

+0

的確如此。我認爲這張海報正在尋找獨特的元素。我想這取決於他的意思是「具體」。 – nrlakin

+0

確實p.s.我沒有投下你的答案,特別是對於一個不清楚的原始問題。 – Chinny84

10

使用list comprehension像這樣:

main_list = [item for item in list_2 if item not in list_1] 

輸出:

>>> list_1 = ["a", "b", "c", "d", "e"] 
>>> list_2 = ["a", "f", "c", "m"] 
>>> 
>>> main_list = [item for item in list_2 if item not in list_1] 
>>> main_list 
['f', 'm'] 
+1

注意:對於較大的'list_1',您需要預先轉換爲'set' /'frozenset',例如'set_1 = frozenset(list_1)',然後'main_list = [list_2中item不在set_1中的項目]',從每個項目的'O(n)'到(大致)'O(1) 。 – ShadowRanger

3
main_list=[] 
list_1=["a", "b", "c", "d", "e"] 
list_2=["a", "f", "c", "m"] 

for i in list_2: 
    if i not in list_1: 
     main_list.append(i) 

print(main_list) 

輸出:

['f', 'm'] 
+0

與[基於等效列表理解的解決方案](http://stackoverflow.com/a/41125957/364696)類似,如果'list_1'很大,並且'list_2'的大小非常小,涉及'len(list_2)'list_1'的O(n)'掃描,使其成爲'O(n * m)'(其中'n'和'm'分別是'list_2'和'list_1'的長度)。如果你將'list_1'轉換爲'set' /'frozenset',那麼可以在'O(1)'中完成包含檢查,從而使總工作數爲''(n)'的長度爲'list_2'(從技術上講,'O(max(n,m))',因爲你做'O(m)'來做'set')。 – ShadowRanger

0

如果出現次數的數量應該考慮到你可能需要使用類似collections.Counter

list_1=["a", "b", "c", "d", "e"] 
list_2=["a", "f", "c", "m"] 
from collections import Counter 
cnt1 = Counter(list_1) 
cnt2 = Counter(list_2) 
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts] 

>>> final 
['f', 'm'] 

正如所承諾的,這也可以處理不同的出現次數的數量爲「差」:

list_1=["a", "b", "c", "d", "e", 'a'] 
cnt1 = Counter(list_1) 
cnt2 = Counter(list_2) 
final = [key for key, counts in cnt2.items() if cnt1.get(key, 0) != counts] 

>>> final 
['a', 'f', 'm'] 
1

如果你想要一個班輪解決方案(忽略進口),只需要對長度n投入O(max(n, m))工作m,不O(n * m)工作,你可以用the itertools module這樣做:

from itertools import filterfalse 

main_list = list(filterfalse(set(list_1).__contains__, list_2)) 

這需要採取結構上的一個回調函數功能功能優勢允許它創建回調一次,並將其用於每個元素,而無需將其存儲在某處(因爲filterfalse在內部存儲它);列表解析和生成器表達式可以做到這一點,但它很醜陋。†

即得到了相同的結果在一個單一的路線爲:

main_list = [x for x in list_2 if x not in list_1] 

與速度:

set_1 = set(list_1) 
main_list = [x for x in list_2 if x not in set_1] 

當然,如果比較旨在是位置,所以:

list_1 = [1, 2, 3] 
list_2 = [2, 3, 4] 

應產生:

main_list = [2, 3, 4] 

(因爲在list_2值有一個匹配的list_1相同指數),你一定要與Patrick's answer,不涉及臨時list S或set S(甚至set S是大致O(1)去,他們有較高的每次檢查的「不變」因子比簡單的相等性檢查)並且涉及O(min(n, m))工作,比任何其他答案都少,並且如果您的問題對位置敏感,那麼當匹配元素出現在不匹配的偏移處時,解決方案是唯一的正確解決方案。

†:做同樣的事情用一個列表理解爲一個班輪途中會有濫用嵌套的循環來創造和緩存值(S)在「最」循環,例如:

main_list = [x for set_1 in (set(list_1),) for x in list_2 if x not in set_1] 

這也給Python 3帶來了較小的性能優勢(因爲現在的set_1在本地範圍內的理解代碼中,而不是從嵌套範圍查找每次檢查;在Python 2中無關緊要,因爲Python 2沒有使用閉包進行列表解析;它們在與它們相同的範圍內操作)。

10

不知道爲什麼上面的解釋是那麼複雜,當你有可用的本地方法:

main_list = list(set(list_2)-set(list_1)) 
+0

保留秩序可能是原因 – Keith

相關問題