如何从列表中删除重复项,同时保持顺序?使用集合删除重复项会破坏原始顺序。 是否有内置的或python的习语?


当前回答

from itertools import groupby
[ key for key,_ in groupby(sortedList)]

这个列表甚至不需要排序,充分条件是相等的值被分组在一起。

编辑:我假设“保持顺序”意味着列表实际上是有序的。如果不是这样,那么MizardX的解决方案是正确的。

社区编辑:然而,这是“将重复的连续元素压缩为单个元素”的最优雅的方法。

其他回答

如果你需要一个班轮,那么这可能会有帮助:

reduce(lambda x, y: x + y if y[0] not in x else x, map(lambda x: [x],lst))

... 应该工作,但纠正我,如果我错了

Pandas用户应该查看Pandas .unique。

>>> import pandas as pd
>>> lst = [1, 2, 1, 3, 3, 2, 4]
>>> pd.unique(lst)
array([1, 2, 3, 4])

该函数返回一个NumPy数组。如果需要,可以使用tolist方法将其转换为列表。

我不是在找死马(这个问题已经很老了,已经有很多好的答案了),但是这里有一个使用熊猫的解决方案,在很多情况下都非常快,而且使用起来非常简单。

import pandas as pd

my_list = [0, 1, 2, 3, 4, 1, 2, 3, 5]

>>> pd.Series(my_list).drop_duplicates().tolist()
# Output:
# [0, 1, 2, 3, 4, 5]

对于另一个非常古老的问题的一个非常晚的回答:

itertools食谱有一个函数可以做到这一点,使用了见集技术,但是:

处理标准键函数。 不使用不体面的黑客。 通过预绑定优化循环。加,而不是查N次。(f7也这样做,但有些版本没有。) 通过使用ifilterfalse优化循环,因此只需遍历Python中唯一的元素,而不是所有元素。(当然,您仍然在ifilterfalse中遍历所有它们,但这是在C中,而且要快得多。)

Is it actually faster than f7? It depends on your data, so you'll have to test it and see. If you want a list in the end, f7 uses a listcomp, and there's no way to do that here. (You can directly append instead of yielding, or you can feed the generator into the list function, but neither one can be as fast as the LIST_APPEND inside a listcomp.) At any rate, usually, squeezing out a few microseconds is not going to be as important as having an easily-understandable, reusable, already-written function that doesn't require DSU when you want to decorate.

和所有的食谱一样,它也有更多的版本。

如果你只想要无键的情况,你可以简化为:

def unique(iterable):
    seen = set()
    seen_add = seen.add
    for element in itertools.ifilterfalse(seen.__contains__, iterable):
        seen_add(element)
        yield element

这里有一些替代选项:http://www.peterbe.com/plog/uniqifiers-benchmark

最快的一个:

def f7(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]

为什么要赋值。添加到seen_add而不是只调用see . Add ?Python是一种动态语言,解析可见。每次迭代添加比解析一个局部变量代价更大。观察。Add可能会在迭代之间发生更改,而运行时还不够聪明,无法排除这种情况。为了安全起见,它必须每次检查对象。

如果您计划在同一个数据集上大量使用这个函数,那么使用一个有序集可能会更好:http://code.activestate.com/recipes/528878/

O(1)每次操作的插入、删除和成员检查。

(小额外注意:see .add()总是返回None,所以以上值只是作为一种尝试更新集合的方式,而不是逻辑测试的组成部分。)