2013-06-01 267 views
2

我試圖從列表中刪除具有相同第一和第三項但僅保留第一項的列表。示例列表和輸出:從列表中刪除某些項目重複的列表

li=[ [2,4,5], [1,3,5], [1,6,5] ] 
output_list = [ [2,4,5], [1,3,5] ] 

我寫的代碼需要很長時間才能執行,因爲原始列表包含數百萬個列表。

b_li = [] 
output_list = [] 
for x in li: 
    s = [ x[0], x[2] ] 
    if s not in b_li: 
     b_li.append(s) 
     output_list.append(x) 

我該如何改進代碼?提前致謝。

+1

使用一個集合而不是一個列表來記錄看到的第一個/最後一個對。 – Marcin

+1

根據您的使用情況,您可以返回迭代器而不是創建新列表。它會爲你節省大量的內存。 – iurisilvio

+0

可能重複? http://stackoverflow.com/questions/15037226/python-remove-duplicate-items-from-nested-list?rq=1 –

回答

2

的改進版本:

b_li = set() 
output_list = [] 
b_li_add = b_li.add 
output_list_append = output_list.append 
for x in li: 
    s = (x[0], x[2]) 
    if s not in b_li: 
     b_li_add(s) 
     output_list_append(x) 

的變化是:

  • 使用set()b_li這使得查找更快。
  • s轉換爲一個元組,因爲不需要將唯一的第一個和第三個元素存儲爲列表。
  • 減少功能查找,加快代碼。
2

使用一組來存儲看到的元素。這是更快:

seen = set() 
res = [] 
for entry in li: 
    cond = (entry[0], entry[2]) 
    if cond not in seen: 
     res.append(entry) 
     seen.add(cond) 


[[2, 4, 5], [1, 3, 5]] 

加成

此外,在想着告訴變量的名稱通常也花時間花。通常情況下,最初的解決方案比預期的要長得多。

+0

+1這是一個簡單,乾淨的解決方案。 –

+0

謝謝,這是一個巨大的飛躍:) –

0

這是一個基於@ iurisilvio的iterator評論並與來自其他人的set爲基礎的解決方案結合使用itertools.compress的解決方案。 而不是從輸入列表中的元素構建output_list,包含布爾值的selector列表是相對於輸入列表中的元素建立的。值爲True表示輸入列表中的相應元素應保留在輸出中。然後可以通過itertools.compressselector應用於輸入列表以產生可迭代的輸出。

from itertools import compress 
li=[ [2,4,5], [1,3,5], [1,6,5] ] 
b_li = set() 
selectors = [] 
for x in li: 
    s = (x[0], x[2]) 
    if s not in b_li: 
     b_li.add(s) 
     selectors.append(True) 
    else: 
     selectors.append(False) 

for x in compress(li, selectors): 
    print x 
[2, 4, 5] 
[1, 3, 5] 
1

利用OrderedDict和詞典具有唯一鍵的事實。

>>> from collections import OrderedDict 
>>> li=[ [2,4,5], [1,3,5], [1,6,5] ] 
>>> OrderedDict(((x[0], x[2]), x) for x in reversed(li)).values() 
[[1, 3, 5], [2, 4, 5]]