2011-03-14 55 views
6

我有兩個列表,l1l2。我需要l1這些不在l2中的物品。從Python中的兩個列表中獲取差異

l1 = [2, 3, 4, 5] 
l2 = [0, 1, 2, 3] 

我只想得到[4,5] - 只有l1的新值。

[i for i in l1 if not i in l2 ] 

我可以不用迭代嗎?

+1

聽起來像過早優化。如果這從根本上說是一個迭代問題,爲什麼你會說'沒有迭代'? – 2011-03-15 05:21:34

回答

6

簡短的回答,是:list(set(l1) - set(l2)),雖然這不會保持順序。

很長的答案,不,因爲內部CPU總是迭代。雖然如果你使用set()迭代將被高度優化,並且將快得多,那麼你的列表理解(更不用說檢查成員資格value in list與集合然後列表更快)。

+0

有人告訴我,內聯迭代也是高度優化的。它與它在執行時的不同之處在於:對於I中的l:do() – Pol 2011-03-14 22:15:53

+0

列表推導(非內聯迭代)實際上比for循環更優化,但設置差異可能是在高速C下完成的,更好。而且因爲你使用的是集合'in'關鍵字(或者C表哥),所以它的速度更快,因此速度更快。 – orlp 2011-03-14 22:18:06

2

如果你不關心元素的順序,你可以使用集:

l1 = set([2, 3, 4, 5]) 
l2 = set([0, 1, 2, 3]) 
print l1 - l2 

打印

set([4, 5]) 
+0

是的..我正在嘗試做類似的事情。我沒有爲我而去。現在可以了。謝謝 – Pol 2011-03-14 22:12:34

1

可以代替使用使用set_1.difference_update(終端SET_2)爲區別:

>>sl1 = set([2, 3, 4, 5]) 
>>sl2 = set([0, 1, 2, 3]) 
>>sl1.difference_update(sl2) 
>>sl1 
set([4, 5]) 
0

將它們轉換爲集合並使用差異運算符:

l1=[2,3,4,5] 
l2=[0,1,2,3] 

answer = set(l1) - set(l2) 
7

你不能沒有迭代就做到這一點。即使你調用一個單一的方法,內部會迭代。

你的做法是罰款一小單子,但你可以使用這種方法,而不是爲更大的名單:

s2 = set(l2) 
result = [i for i in l1 if not i in s2 ] 

這將是快,也將維持在L1的元素的原始順序。

0

如下您可以簡單地這樣做:

list(set(l1) - set(l2)) 

這應該做的伎倆。

1

當您的列表元素可以轉換爲集時,轉換爲集很好。否則,你需要類似Mark Byers' solution。如果你有大的列表進行比較,你可能不希望支付的內存分配開銷並簡化了線路:

[l1.remove(m) for m in l1 if m in l2] 
+0

歡迎來到SO。也許你應該重新考慮你的答案,因爲OP似乎想要一個無迭代解決方案。我想他的意思不是for循環,即使不是列表理解。所以也許地圖或過濾器解決方案會更合適。我也不認爲他想改變原來的名單。 – 2012-11-08 22:31:36

-1

例子:

>>a = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] 
>>b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] 

我們可以連接並獲得完整的區別:

>>list (set(a) -set(b)) + list (set(b) -set(a)) 
>>[89, 34, 21, 55, 4, 6, 7, 9, 10, 11, 12] 
0

使用內置模塊set

>>> a = set([1,2,3,4,5]) 
>>> b = set([1,3,5]) 
>>> a.difference(b) 
set([2, 4]) 

另一種方法

>>> a = set([1,2,3,4,5]) 
>>> b = [1,3,5] 
>>> a.difference(b) 
set([2, 4]) 
相關問題