Deleting repeats in a list python
Possible Duplicates:
How do you remove duplicates from a list in Python whilst preserving order?
In Python, what is the fastest algorithm for removing duplicates from a list so that all elements are unique while preserving order?
我想知道是否有一个函数可以执行以下操作:
将列表作为参数:
1 | list = [ 3 , 5 , 6 , 4 , 6 , 2 , 7 , 6 , 5 , 3 ] |
并删除列表中的所有重复项以获得:
1 | list = [ 3 , 5 , 6 , 4 , 2 , 7 ] |
我知道你可以把它转换成一本字典,并利用这样一个事实:字典不能重复,但我想知道是否有更好的方法。
谢谢
请参阅python文档,以了解实现这一点的三种方法。以下内容是从该站点复制的。将示例"mylist"替换为变量名("list")。
第一个示例:如果您不介意重新排序列表,请对其进行排序,然后从列表的末尾进行扫描,并在执行以下操作时删除重复项:
1 2 3 4 5 6 7 8 | if mylist: mylist.sort() last = mylist[-1] for i in range(len(mylist)-2, -1, -1): if last == mylist[i]: del mylist[i] else: last = mylist[i] |
第二个示例:如果列表中的所有元素都可以用作字典键(即它们都是可哈希的),则通常更快:
1 2 3 4 | d = {} for x in mylist: d[x] = 1 mylist = list(d.keys()) |
第三个示例:在python 2.5及更高版本中:
1 | mylist = list(set(mylist)) |
尽管你说你不一定要用
1 2 3 4 5 | from collections import OrderedDict l = [3 ,5 ,6 ,4 ,6 ,2 ,7 ,6 ,5 ,3] OrderedDict.fromkeys(l).keys() # [3, 5, 6, 4, 2, 7] |
请注意,这将保留原始顺序。
在编写这个答案时,唯一能保持顺序的解决方案是ordereddict解决方案,以及Dave稍微详细一点的解决方案。
下面是另一种在迭代时滥用副作用的方法,这比ordereddict解决方案更为冗长:
1 2 3 4 5 | def uniques(iterable): seen = set() sideeffect = lambda _: True return [x for x in iterable if (not x in seen) and sideeffect(seen.add(x))] |
1 2 3 4 5 6 7 8 | s = set() result = [] for item in l: if item not in s: s.add(item) result.append(item) print result |
这将在o(n)中运行,其中n是原始列表的长度。
首先,不要将它命名为隐藏在内置类型列表中的列表。比如说,
为了解决你的问题,我最常看到的就是
set是一个无序的容器,它只有唯一的元素,并且提供(我认为)o(1)插入和检查成员身份
下面是我自己收集的一个有用的python工具片段——这使用了Ninjagecko在回答中使用的"滥用的副作用"方法。这还需要努力处理非哈希值,并返回与传入的序列类型相同的序列:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | def unique(seq, keepstr=True): """Function to keep only the unique values supplied in a given sequence, preserving original order.""" # determine what type of return sequence to construct if isinstance(seq, (list,tuple)): returnType = type(seq) elif isinstance(seq, basestring): returnType = (list, type(seq)('').join)[bool(keepstr)] else: # - generators and their ilk should just return a list returnType = list try: seen = set() return returnType(item for item in seq if not (item in seen or seen.add(item))) except TypeError: # sequence items are not of a hashable type, can't use a set for uniqueness seen = [] return returnType(item for item in seq if not (item in seen or seen.append(item))) |
这里有各种各样的调用,有各种类型的序列/迭代器/生成器:
1 2 3 4 5 6 7 | from itertools import chain print unique("ABC") print unique(list("ABABBAC")) print unique(range(10)) print unique(chain(reversed(range(5)), range(7))) print unique(chain(reversed(xrange(5)), xrange(7))) print unique(i for i in chain(reversed(xrange(5)), xrange(7)) if i % 2) |
印刷品:
1 2 3 4 5 6 | ABC ['A', 'B', 'C'] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] [4, 3, 2, 1, 0, 5, 6] [4, 3, 2, 1, 0, 5, 6] [3, 1, 5] |
一个集合比一个复杂的字典术语更好。但这两种方法都会使您的排序变得松散(除非您使用有序字典,否则会再次增加复杂性)。
正如其他海报上所说,解决方案并不难:
1 2 | l = [ 3 , 5 , 6 , 4 , 6 , 2 , 7 , 6 , 5 , 3 ] list(set(l)) |
保持订单的方法是:
1 2 3 4 5 6 7 | def uniques(l): seen = set() for i in l: if i not in seen: seen.add(i) yield i |
或者,以一种不太可读的方式:
1 2 3 | def uniques(l): seen = set() return (seen.add(i) or i for i in l if i not in seen) |
然后您可以这样使用它:
1 2 3 | l = [ 3 , 5 , 6 , 4 , 6 , 2 , 7 , 6 , 5 , 3 ] list(uniques(l)) >>> [3, 5, 6, 4, 2, 7] |