2011-11-01 87 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

不错。它需要一分钟才能看到它的工作原理。聪明。 –

相关问题