我如何检查一个列表是否有任何重复,并返回一个没有重复的新列表?


当前回答

从列表中删除重复项的最佳方法是使用set()函数,该函数在python中可用,再次将该集合转换为列表

In [2]: some_list = ['a','a','v','v','v','c','c','d']
In [3]: list(set(some_list))
Out[3]: ['a', 'c', 'd', 'v']

其他回答

我没有看到非哈希值的答案,一行,nlog n,标准库,所以这是我的答案:

list(map(operator.itemgetter(0), itertools.groupby(sorted(items))))

或作为一个生成函数:

def unique(items: Iterable[T]) -> Iterable[T]:
    """For unhashable items (can't use set to unique) with a partial order"""
    yield from map(operator.itemgetter(0), itertools.groupby(sorted(items)))

到目前为止,我看到的所有保持顺序的方法要么使用朴素比较(时间复杂度最多为O(n^2)),要么使用限制于可哈希输入的重载OrderedDicts/set+list组合。下面是一个与哈希无关的O(nlogn)解决方案:

更新增加了关键参数、文档和Python 3兼容性。

# from functools import reduce <-- add this import on Python 3

def uniq(iterable, key=lambda x: x):
    """
    Remove duplicates from an iterable. Preserves order. 
    :type iterable: Iterable[Ord => A]
    :param iterable: an iterable of objects of any orderable type
    :type key: Callable[A] -> (Ord => B)
    :param key: optional argument; by default an item (A) is discarded 
    if another item (B), such that A == B, has already been encountered and taken. 
    If you provide a key, this condition changes to key(A) == key(B); the callable 
    must return orderable objects.
    """
    # Enumerate the list to restore order lately; reduce the sorted list; restore order
    def append_unique(acc, item):
        return acc if key(acc[-1][1]) == key(item[1]) else acc.append(item) or acc 
    srt_enum = sorted(enumerate(iterable), key=lambda item: key(item[1]))
    return [item[1] for item in sorted(reduce(append_unique, srt_enum, [srt_enum[0]]))] 

这只是一个可读的函数,很容易理解,我已经使用了dict数据结构,我已经使用了一些内置函数和更好的复杂度O(n)

def undup(dup_list):
    b={}
    for i in dup_list:
        b.update({i:1})
    return b.keys()
a=["a",'b','a']
print undup(a)

免责声明:你可能会得到缩进错误(如果复制和粘贴),使用上述代码与适当的缩进粘贴之前

它需要安装一个第三方模块,但包iteration_utilities包含一个unique_everseen1函数,可以删除所有重复的同时保留顺序:

>>> from iteration_utilities import unique_everseen

>>> list(unique_everseen(['a', 'b', 'c', 'd'] + ['a', 'c', 'd']))
['a', 'b', 'c', 'd']

如果你想避免列表添加操作的开销,你可以使用itertools。链:

>>> from itertools import chain
>>> list(unique_everseen(chain(['a', 'b', 'c', 'd'], ['a', 'c', 'd'])))
['a', 'b', 'c', 'd']

unique_everseen也适用于列表中有不可哈希项(例如列表)的情况:

>>> from iteration_utilities import unique_everseen
>>> list(unique_everseen([['a'], ['b'], 'c', 'd'] + ['a', 'c', 'd']))
[['a'], ['b'], 'c', 'd', 'a']

然而,这将比项目是可哈希的(多)慢。


1披露:我是iteration_utilities-library的作者。

我的列表中有一个字典,所以我不能使用上面的方法。我得到了错误:

TypeError: unhashable type:

如果你关心顺序和/或某些项是不可散列的。那么你可能会发现这个很有用:

def make_unique(original_list):
    unique_list = []
    [unique_list.append(obj) for obj in original_list if obj not in unique_list]
    return unique_list

有些人可能认为带副作用的列表理解不是一个好的解决方案。这里有一个替代方案:

def make_unique(original_list):
    unique_list = []
    map(lambda x: unique_list.append(x) if (x not in unique_list) else False, original_list)
    return unique_list