协慌网

登录 贡献 社区

删除列表中的重复项

几乎我需要编写一个程序来检查列表是否有任何重复项,如果有,它会删除它们并返回一个新列表,其中包含未复制 / 删除的项目。这就是我所拥有的,但说实话,我不知道该怎么做。

def remove_duplicates():
    t = ['a', 'b', 'c', 'd']
    t2 = ['a', 'c', 'd']
    for t in t2:
        t.append(t.remove())
    return t

答案

获取唯一项目集合的常用方法是使用set 。集合是不同对象的无序集合。要从任何可迭代创建集合,您只需将其传递给内置的set()函数即可。如果您以后需要再次使用真实列表,则可以类似地将该集传递给list()函数。

以下示例应涵盖您尝试执行的操作:

>>> t = [1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> t
[1, 2, 3, 1, 2, 5, 6, 7, 8]
>>> list(set(t))
[1, 2, 3, 5, 6, 7, 8]
>>> s = [1, 2, 3]
>>> list(set(t) - set(s))
[8, 5, 6, 7]

从示例结果中可以看出,未维护原始订单。如上所述,集合本身是无序集合,因此订单丢失。将集合转换回列表时,会创建任意顺序。

如果订单对您很重要,那么您将不得不使用不同的机制。一个非常常见的解决方案是依靠OrderedDict在插入过程中保持键的顺序:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]

请注意,这会产生首先创建字典,然后从中创建列表的开销。因此,如果您实际上不需要保留订单,那么最好使用一套。查看此问题以获取更多详细信息以及删除重复项时保留订单的其他方法。


最后请注意, setOrderedDict解决方案都要求您的项目可以清洗 。这通常意味着它们必须是不可变的。如果你必须处理不可清除的项目(例如列表对象),那么你将不得不使用一种缓慢的方法,在这种方法中你基本上必须将每个项目与嵌套循环中的每个其他项目进行比较。

在 Python 2.7 中 ,从迭代中删除重复项同时保持原始顺序的新方法是:

>>> from collections import OrderedDict
>>> list(OrderedDict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

在 Python 3.5 中 ,OrderedDict 有一个 C 实现。我的时间表明,现在这是 Python 3.5 的各种方法中最快和最短的。

在 Python 3.6 中 ,常规字典变得有序且紧凑。 (此功能适用于 CPython 和 PyPy,但在其他实现中可能不存在)。这为我们提供了一种新的最快的扣除方式,同时保留了订单:

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

在 Python 3.7 中 ,保证常规字典在所有实现中都有序。 因此,最短和最快的解决方案是:

>>> list(dict.fromkeys('abracadabra'))
['a', 'b', 'r', 'c', 'd']

这是一个单行: list(set(source_list))list(set(source_list))

set是不可能有重复的东西。

更新:订单保留方法有两行:

from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()

这里我们使用OrderedDict记住键的插入顺序的事实,并且在更新特定键的值时不会更改它。我们插入True作为值,但我们可以插入任何内容,只是不使用值。 ( set很像一个带有忽略值的dict 。)