2009-11-04 109 views
10

我有兩個非常大的列表,並通過它循環一次至少需要一秒鐘,我需要做到200,000次。刪除兩個列表中的重複項以形成重複項的最快方法是什麼?刪除列表中的重複項的最快方法Python

+0

您的時間表明一個循環目前需要55個小時。聽聽提出的解決方案需要多長時間會很有意思。 – behindthefall 2009-11-05 13:45:40

回答

20

這是我能想到的最快方法:

import itertools 
output_list = list(set(itertools.chain(first_list, second_list))) 

輕微更新:作爲jcd指出,根據您的應用程序,你可能並不需要將結果轉換回列表。由於一組是由本身迭代,你也許可以只直接使用它:

output_set = set(itertools.chain(first_list, second_list)) 
for item in output_set: 
    # do something 

要小心的是,涉及使用set()可能會重新排序列表中的元素,所以沒有保證元素的任何解決方案將以任何特定的順序。這就是說,既然你把兩個列表結合在一起,很難想出一個很好的理由說明爲什麼你需要對它們進行特定的排序,所以這可能不是你需要擔心的。

+0

哦,你的解決方案比我的更好:) – shylent 2009-11-04 17:22:27

+0

感謝大家的回答,他們都幫了很大的忙! :) – Cookies 2009-11-04 17:38:15

+1

+1。如果命令*很重要,那麼也許一個有序集合將會這樣做:http://stackoverflow.com/questions/1653970/does-python-have-an-ordered-set – Stephan202 2009-11-04 17:38:57

3
result = list(set(list1).union(set(list2))) 

這就是我該怎麼做的。儘管如此,我對演出不太確定,但肯定比手動演奏更好。

+0

'set.union(self,other)'與任何迭代都很好,因爲'other' – u0b34a0f6ae 2009-11-04 18:17:52

7

由於丹尼爾指出,一組不能包含重複的條目 - 所以串連名單:

list1 + list2 

新的名單,然後轉換爲一組:

set(list1 + list2) 

然後回到列表:

list(set(list1 + list2)) 
+2

感謝您解釋我的代碼在做什麼。擊敗我! :-)我只想提到我編輯我的答案使用'itertools.chain()'而不是僅僅連接列表的原因是因爲它避免了在內存中分配第三個大的列表。 'set()'構造函數實際上並不需要列表,它只需要一個可迭代所有元素的迭代器,'itertools.chain()'可以更有效地執行(避免複製)。 – 2009-11-04 17:27:04

11

我推薦這樣的:

def combine_lists(list1, list2): 
    s = set(list1) 
    s.update(list2) 
    return list(s) 

這消除了創建頭兩個連接的怪物列表的問題。

根據你在輸出中做什麼,不要費心地轉換回列表。如果訂購是重要的,你可能需要某種裝飾/排序/ undecorate shenanig圍繞此。

+2

同意,沒有必要連接兩個列表 - 這只是浪費內存。我希望看到調用's.update(list2)'與上面使用的迭代器方法之間的性能差異。你的方法可能會稍微快一點。但是,正如您指出的那樣,通過簡單地不轉換回最終列表,您可以獲得更大的性能節省。 – 2009-11-04 17:34:18

+1

我跑了幾個時間點,它似乎有所不同,這是更快,但從來沒有超過5%或10%的方式。我會稱之爲平局。 – jcdyer 2009-11-04 18:14:56

+0

由於itertools只是鏈接兩個對象,我認爲它的影響是非常小的,所以問題是set()是一個大的列表還是set()一半的列表和.update() )其餘的。看起來沒有。 – jcdyer 2009-11-04 18:17:46