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


当前回答

如果你想保持顺序,不使用任何外部模块,这里有一个简单的方法:

>>> t = [1, 9, 2, 3, 4, 5, 3, 6, 7, 5, 8, 9]
>>> list(dict.fromkeys(t))
[1, 9, 2, 3, 4, 5, 6, 7, 8]

注意:这种方法保留了出现的顺序,因此,如上所示,9将在1之后,因为它是第一次出现。然而,这和你做的结果是一样的

from collections import OrderedDict
ulist=list(OrderedDict.fromkeys(l))

但它更短,跑得更快。

这是因为每次fromkeys函数尝试创建一个新键时,如果值已经存在,它就会简单地覆盖它。然而,这不会影响字典,因为fromkeys创建的字典中所有键的值都为None,因此有效地消除了所有重复的值。

其他回答

很晚才回答。 如果你不关心列表顺序,你可以使用*arg扩展集唯一性来删除dupes,即:

l = [*{*l}]

Python3演示

Python内置了许多函数,您可以使用set()来删除列表中的重复项。 根据你的例子,下面有两个列表t和t2

t = ['a', 'b', 'c', 'd']
t2 = ['a', 'c', 'd']
result = list(set(t) - set(t2))
result

答:[b]

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

下面的例子应该涵盖你要做的任何事情:

>>> t = [1, 2, 3, 1, 2, 3, 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]

从Python 3.7开始,内置字典也保证保持插入顺序,所以如果你使用的是Python 3.7或更高版本(或CPython 3.6),你也可以直接使用它:

>>> list(dict.fromkeys(t))
[1, 2, 3, 5, 6, 7, 8]

请注意,这可能会有一些开销,首先创建一个字典,然后从它创建一个列表。如果您实际上不需要保留顺序,那么使用集合通常会更好,特别是因为它提供了更多的操作。查看这个问题,了解更多细节和在删除重复项时保留顺序的替代方法。


最后请注意,set和OrderedDict/dict解决方案都要求项是可哈希的。这通常意味着它们必须是不可变的。如果你必须处理不可哈希的项(例如列表对象),那么你将不得不使用一种缓慢的方法,你基本上必须在一个嵌套循环中比较每个项。

我已将各种建议与perfplot进行了比较。事实证明,如果输入数组没有重复的元素,所有方法的速度或多或少都一样快,与输入数据是Python列表还是NumPy数组无关。

如果输入数组很大,但只包含一个唯一元素,则set、dict和np。如果输入数据是一个列表,唯一方法是常量时间的。如果是NumPy数组,np。Unique比其他选项快10倍。

让我有点惊讶的是这些也不是常时间运算。


代码重现图:

import perfplot
import numpy as np
import matplotlib.pyplot as plt


def setup_list(n):
    # return list(np.random.permutation(np.arange(n)))
    return [0] * n


def setup_np_array(n):
    # return np.random.permutation(np.arange(n))
    return np.zeros(n, dtype=int)


def list_set(data):
    return list(set(data))


def numpy_unique(data):
    return np.unique(data)


def list_dict(data):
    return list(dict.fromkeys(data))


b = perfplot.bench(
    setup=[
        setup_list,
        setup_list,
        setup_list,
        setup_np_array,
        setup_np_array,
        setup_np_array,
    ],
    kernels=[list_set, numpy_unique, list_dict, list_set, numpy_unique, list_dict],
    labels=[
        "list(set(lst))",
        "np.unique(lst)",
        "list(dict(lst))",
        "list(set(arr))",
        "np.unique(arr)",
        "list(dict(arr))",
    ],
    n_range=[2 ** k for k in range(23)],
    xlabel="len(array)",
    equality_check=None,
)
# plt.title("input array = [0, 1, 2,..., n]")
plt.title("input array = [0, 0,..., 0]")
b.save("out.png")
b.show()

如果你不关心顺序,就这样做:

def remove_duplicates(l):
    return list(set(l))

一个集合保证没有重复项。