我有这样的数据结构:
[
[('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 :(得分: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)))
如果您只能假定可订购元素,这里使用bisect模块的变体。给定具有 r 唯一值的 n 输入,其搜索步骤花费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
答案 1 :(得分: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']