如何在整数列表中找到重复项并创建重复项的另一个列表?


当前回答

简单地检查,对于所有列表项,如果一个项的第一个索引等于该项的最后一个索引:

>>> lastindex = lambda arr, el: len(arr) - arr[::-1].index(el) -1
>>> is_duplicate  = lambda arr, el: arr.index(el) != lastindex(arr, el)
>>> duplicates = lambda arr: [*set(x for x in arr if is_duplicate(arr, x))]
>>> 
>>> a=[2,3,5,7,11,13, 2,17,7,7,17,18,3,19,5,2,7,48,48,2,19]
>>> duplicates(a)
[2, 3, 5, 7, 48, 17, 19]
>>> 

其他回答

一句话解决方案:

set([i for i in list if sum([1 for a in list if a == i]) > 1])

我们可以使用itertools。Groupby,以便找到所有有dup的项:

from itertools import groupby

myList  = [2, 4, 6, 8, 4, 6, 12]
# when the list is sorted, groupby groups by consecutive elements which are similar
for x, y in groupby(sorted(myList)):
    #  list(y) returns all the occurences of item x
    if len(list(y)) > 1:
        print x  

输出将是:

4
6

使用sort()函数。重复项可以通过遍历它并检查l1[i] == l1[i+1]来识别。

尽管它的复杂度是O(n log n),但这似乎有点竞争性,请参阅下面的基准测试。

a = sorted(a)
dupes = list(set(a[::2]) & set(a[1::2]))

排序会把副本放在一起,所以它们都在偶数下标和奇数下标处。唯一值只能在偶数或奇数下标处存在,不能同时存在。所以偶数下标值和奇数下标值的交集就是重复项。

基准测试结果:

这使用了MSeifert的基准测试,但只使用了从接受的答案(georgs)、最慢的解决方案、最快的解决方案(不包括it_duplcopies,因为它不唯一重复)和我的解决方案。否则就太拥挤了,颜色也太相似了。

如果允许修改给定的列表,那么第一行可以是a.sort(),这样会快一些。但是基准会多次重用相同的列表,因此修改它会打乱基准。

显然set(a[::2]).intersection(a[1::2])不会创建第二个集合,而且速度会快一点,但它也会长一点。

假设我们有这个元素列表:

a = [1, 2, 3, 2, 1, 5, 6, 5, 5, 5]

我们可以只使用集合来找到唯一的元素:

unique = set()
for num in a:
    if num not in unique:
        unique.add(num)
    else:
        unique = unique - set([num])

最后:

>>> unique
{3, 6}

如果你想要得到副本,你可以简单地做:

>>> duplicates = set(a) - unique
>>> duplicates
{1, 2, 5}

注:

集合中的元素查找是O(1) 从集合中移除的元素是O(1)