2011-11-01 82 views
9

我有一個這樣的數據結構:在保留順序的同時從包含不可保存元素的Python列表中刪除重複元素?

[ 
[('A', '1'), ('B', '2')], 
[('A', '1'), ('B', '2')], 
[('A', '4'), ('C', '5')] 
] 

我想獲得此:

[ 
[('A', '1'), ('B', '2')], 
[('A', '4'), ('C', '5')] 
] 

是否有這樣做的同時維持秩序如圖所示的一個好辦法嗎?

命令拷貝粘貼:

sample = [] 
sample.append([('A', '1'), ('B', '2')]) 
sample.append([('A', '1'), ('B', '2')]) 
sample.append([('A', '4'), ('C', '5')]) 
+0

是重複總是相鄰? – Cameron

+0

@Cameron:不一定。 – Legend

回答

7

這是廣受著名Pythonista早就回答了一個小有名氣的問題:http://code.activestate.com/recipes/52560-remove-duplicates-from-a-sequence/

如果你能承擔相等的記錄是相鄰的,有在itertools docs配方:

from operator import itemgetter 
from itertools import groupby, imap 

def unique_justseen(iterable, key=None): 
    "List unique elements, preserving order. Remember only the element just seen." 
    # unique_justseen('AAAABBBCCDAABBB') --> A B C D A B 
    # unique_justseen('ABBCcAD', str.lower) --> A B C A D 
    return imap(next, imap(itemgetter(1), groupby(iterable, key))) 

如果可以使用對開米只承擔訂購的元素,這裏的變體odule。給定n輸入爲r唯一值,其搜索步驟的成本爲O(n log r)。如果找到新的唯一值,則將其插入看到的列表中,成本爲O(r * r)。

from bisect import bisect_left, insort 

def dedup(seq): 
    'Remove duplicates. Preserve order first seen. Assume orderable, but not hashable elements' 
    result = [] 
    seen = [] 
    for x in seq: 
     i = bisect_left(seen, x) 
     if i == len(seen) or seen[i] != x: 
      seen.insert(i, x) 
      result.append(x) 
    return result 
+0

蒂姆彼得斯唯一的訂單保留配方是強力。儘管如此,可以修改排序配方以保持O(n log n)性能,同時保持順序。 –

+0

保留訂單的變體由Alex Martelli提供,並在評論中列在Tim的代碼中。 –

+2

據我所知,Alex Martelli的變種都假設可行性。 –

5

這裏是排序/獨特成語的順序保留變體。這會給你O(n log n)的表現,只要你的物品至少可以排序。

def unique(a): 
    indices = sorted(range(len(a)), key=a.__getitem__) 
    indices = set(next(it) for k, it in 
        itertools.groupby(indices, key=a.__getitem__)) 
    return [x for i, x in enumerate(a) if i in indices] 

實施例(具有可哈希項爲簡單起見):

>>> a = ['F', 'J', 'B', 'F', 'V', 'A', 'E', 'U', 'B', 'U', 'Z', 'K'] 
>>> unique(a) 
['F', 'J', 'B', 'V', 'A', 'E', 'U', 'Z', 'K'] 
+0

不錯。它需要一分鐘才能看到它的工作原理。聰明。 –

相關問題