我如何找到一个列表中的重复,并与他们创建另一个列表?

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

1222531 次浏览

要删除重复的使用set(a)。要打印副本,可以这样做:

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


import collections
print([item for item, count in collections.Counter(a).items() if count > 1])


## [1, 2, 5]

请注意,Counter不是特别有效(计时),在这里可能会过度使用。set将表现更好。这段代码以源顺序计算一个唯一元素的列表:

seen = set()
uniq = []
for x in a:
if x not in seen:
uniq.append(x)
seen.add(x)

或者,更简洁地说:

seen = set()
uniq = [x for x in a if x not in seen and not seen.add(x)]

我不推荐后一种风格,因为not seen.add(x)在做什么并不明显(设置add()方法总是返回None,因此需要not)。

计算没有库的重复元素列表:

seen = set()
dupes = []


for x in a:
if x in seen:
dupes.append(x)
else:
seen.add(x)

或者,更简洁地说:

seen = set()
dupes = [x for x in a if x in seen or seen.add(x)]

如果列表元素不可哈希,则不能使用set /dicts,必须使用二次时间解决方案(逐个比较)。例如:

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


no_dupes = [x for n, x in enumerate(a) if x not in a[:n]]
print no_dupes # [[1], [2], [3], [5]]


dupes = [x for n, x in enumerate(a) if x in a[:n]]
print dupes # [[1], [3]]

集合。Counter是python 2.7中的新功能:


Python 2.5.4 (r254:67916, May 31 2010, 15:03:39)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
a = [1,2,3,2,1,5,6,5,5,5]
import collections
print [x for x, y in collections.Counter(a).items() if y > 1]
Type "help", "copyright", "credits" or "license" for more information.
File "", line 1, in
AttributeError: 'module' object has no attribute 'Counter'
>>>

在早期版本中,你可以使用传统的字典:

a = [1,2,3,2,1,5,6,5,5,5]
d = {}
for elem in a:
if elem in d:
d[elem] += 1
else:
d[elem] = 1


print [x for x, y in d.items() if y > 1]

你不需要计数,只需要该物品之前是否被看到过。调整这个答案到这个问题:

def list_duplicates(seq):
seen = set()
seen_add = seen.add
# adds all elements it doesn't know yet to seen and all other to seen_twice
seen_twice = set( x for x in seq if x in seen or seen_add(x) )
# turn the set into a list (as requested)
return list( seen_twice )


a = [1,2,3,2,1,5,6,5,5,5]
list_duplicates(a) # yields [1, 2, 5]

以防速度很重要,这里有一些时间安排:

# file: test.py
import collections


def thg435(l):
return [x for x, y in collections.Counter(l).items() if y > 1]


def moooeeeep(l):
seen = set()
seen_add = seen.add
# adds all elements it doesn't know yet to seen and all other to seen_twice
seen_twice = set( x for x in l if x in seen or seen_add(x) )
# turn the set into a list (as requested)
return list( seen_twice )


def RiteshKumar(l):
return list(set([x for x in l if l.count(x) > 1]))


def JohnLaRooy(L):
seen = set()
seen2 = set()
seen_add = seen.add
seen2_add = seen2.add
for item in L:
if item in seen:
seen2_add(item)
else:
seen_add(item)
return list(seen2)


l = [1,2,3,2,1,5,6,5,5,5]*100

以下是结果:(做得好@JohnLaRooy!)

$ python -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
10000 loops, best of 3: 74.6 usec per loop
$ python -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
10000 loops, best of 3: 91.3 usec per loop
$ python -mtimeit -s 'import test' 'test.thg435(test.l)'
1000 loops, best of 3: 266 usec per loop
$ python -mtimeit -s 'import test' 'test.RiteshKumar(test.l)'
100 loops, best of 3: 8.35 msec per loop

有趣的是,除了计时本身,当使用pypy时,排名也略有变化。最有趣的是,基于counter的方法极大地受益于pypy的优化,而我建议的方法缓存方法似乎几乎没有任何效果。

$ pypy -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
100000 loops, best of 3: 17.8 usec per loop
$ pypy -mtimeit -s 'import test' 'test.thg435(test.l)'
10000 loops, best of 3: 23 usec per loop
$ pypy -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
10000 loops, best of 3: 39.3 usec per loop

显然,这种效应与输入数据的“重复性”有关。我设置了l = [random.randrange(1000000) for i in xrange(10000)],得到了这些结果:

$ pypy -mtimeit -s 'import test' 'test.moooeeeep(test.l)'
1000 loops, best of 3: 495 usec per loop
$ pypy -mtimeit -s 'import test' 'test.JohnLaRooy(test.l)'
1000 loops, best of 3: 499 usec per loop
$ pypy -mtimeit -s 'import test' 'test.thg435(test.l)'
1000 loops, best of 3: 1.68 msec per loop

一个非常简单的解决方案,但是复杂度是O(n*n)。

>>> xs = [1,2,3,4,4,5,5,6,1]
>>> set([x for x in xs if xs.count(x) > 1])
set([1, 4, 5])
list2 = [1, 2, 3, 4, 1, 2, 3]
lset = set()
[(lset.add(item), list2.append(item))
for item in list2 if item not in lset]
print list(lset)
有点晚了,但可能对一些人有帮助。 对于一个较大的列表,我发现这对我有用
l=[1,2,3,5,4,1,3,1]
s=set(l)
d=[]
for x in l:
if x in s:
s.remove(x)
else:
d.append(x)
d
[1,3,1]

显示正确和所有重复,并保持秩序。

一句话解决方案:

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

我在寻找相关的东西时遇到了这个问题-想知道为什么没有人提供基于生成器的解决方案?解决这个问题的方法是:

>>> print list(getDupes_9([1,2,3,2,1,5,6,5,5,5]))
[1, 2, 5]

我很关心可伸缩性,所以测试了几种方法,包括在小列表上工作得很好的naive项,但随着列表变大,可伸缩性很差(注意-使用timeit会更好,但这只是说明)。

我加入了@moooeeeep作为比较(它的速度非常快:如果输入列表是完全随机的,速度最快)和itertools方法,对于大多数排序的列表,它甚至更快……现在包括来自@ fireynx的熊猫方法-缓慢,但不是可怕的,而且简单。注意:在我的机器上,sort/tee/zip方法对于大型有序列表始终是最快的,moooeeeep对于洗牌列表是最快的,但您的情况可能会有所不同。

优势

  • 非常快速简单的测试'任何'重复使用相同的代码

假设

  • 重复项只应报告一次
  • 重复的订单不需要保留
  • Duplicate可能位于列表中的任何位置

最快的解决方案,1m条目:

def getDupes(c):
'''sort/tee/izip'''
a, b = itertools.tee(sorted(c))
next(b, None)
r = None
for k, g in itertools.izip(a, b):
if k != g: continue
if k != r:
yield k
r = k

方法测试

import itertools
import time
import random


def getDupes_1(c):
'''naive'''
for i in xrange(0, len(c)):
if c[i] in c[:i]:
yield c[i]


def getDupes_2(c):
'''set len change'''
s = set()
for i in c:
l = len(s)
s.add(i)
if len(s) == l:
yield i


def getDupes_3(c):
'''in dict'''
d = {}
for i in c:
if i in d:
if d[i]:
yield i
d[i] = False
else:
d[i] = True


def getDupes_4(c):
'''in set'''
s,r = set(),set()
for i in c:
if i not in s:
s.add(i)
elif i not in r:
r.add(i)
yield i


def getDupes_5(c):
'''sort/adjacent'''
c = sorted(c)
r = None
for i in xrange(1, len(c)):
if c[i] == c[i - 1]:
if c[i] != r:
yield c[i]
r = c[i]


def getDupes_6(c):
'''sort/groupby'''
def multiple(x):
try:
x.next()
x.next()
return True
except:
return False
for k, g in itertools.ifilter(lambda x: multiple(x[1]), itertools.groupby(sorted(c))):
yield k


def getDupes_7(c):
'''sort/zip'''
c = sorted(c)
r = None
for k, g in zip(c[:-1],c[1:]):
if k == g:
if k != r:
yield k
r = k


def getDupes_8(c):
'''sort/izip'''
c = sorted(c)
r = None
for k, g in itertools.izip(c[:-1],c[1:]):
if k == g:
if k != r:
yield k
r = k


def getDupes_9(c):
'''sort/tee/izip'''
a, b = itertools.tee(sorted(c))
next(b, None)
r = None
for k, g in itertools.izip(a, b):
if k != g: continue
if k != r:
yield k
r = k


def getDupes_a(l):
'''moooeeeep'''
seen = set()
seen_add = seen.add
# adds all elements it doesn't know yet to seen and all other to seen_twice
for x in l:
if x in seen or seen_add(x):
yield x


def getDupes_b(x):
'''iter*/sorted'''
x = sorted(x)
def _matches():
for k,g in itertools.izip(x[:-1],x[1:]):
if k == g:
yield k
for k, n in itertools.groupby(_matches()):
yield k


def getDupes_c(a):
'''pandas'''
import pandas as pd
vc = pd.Series(a).value_counts()
i = vc[vc > 1].index
for _ in i:
yield _


def hasDupes(fn,c):
try:
if fn(c).next(): return True    # Found a dupe
except StopIteration:
pass
return False


def getDupes(fn,c):
return list(fn(c))


STABLE = True
if STABLE:
print 'Finding FIRST then ALL duplicates, single dupe of "nth" placed element in 1m element array'
else:
print 'Finding FIRST then ALL duplicates, single dupe of "n" included in randomised 1m element array'
for location in (50,250000,500000,750000,999999):
for test in (getDupes_2, getDupes_3, getDupes_4, getDupes_5, getDupes_6,
getDupes_8, getDupes_9, getDupes_a, getDupes_b, getDupes_c):
print 'Test %-15s:%10d - '%(test.__doc__ or test.__name__,location),
deltas = []
for FIRST in (True,False):
for i in xrange(0, 5):
c = range(0,1000000)
if STABLE:
c[0] = location
else:
c.append(location)
random.shuffle(c)
start = time.time()
if FIRST:
print '.' if location == test(c).next() else '!',
else:
print '.' if [location] == list(test(c)) else '!',
deltas.append(time.time()-start)
print ' -- %0.3f  '%(sum(deltas)/len(deltas)),
print
print

“all dupes”测试的结果是一致的,在这个数组中找到“first”重复,然后是“all”重复:

Finding FIRST then ALL duplicates, single dupe of "nth" placed element in 1m element array
Test set len change :    500000 -  . . . . .  -- 0.264   . . . . .  -- 0.402
Test in dict        :    500000 -  . . . . .  -- 0.163   . . . . .  -- 0.250
Test in set         :    500000 -  . . . . .  -- 0.163   . . . . .  -- 0.249
Test sort/adjacent  :    500000 -  . . . . .  -- 0.159   . . . . .  -- 0.229
Test sort/groupby   :    500000 -  . . . . .  -- 0.860   . . . . .  -- 1.286
Test sort/izip      :    500000 -  . . . . .  -- 0.165   . . . . .  -- 0.229
Test sort/tee/izip  :    500000 -  . . . . .  -- 0.145   . . . . .  -- 0.206  *
Test moooeeeep      :    500000 -  . . . . .  -- 0.149   . . . . .  -- 0.232
Test iter*/sorted   :    500000 -  . . . . .  -- 0.160   . . . . .  -- 0.221
Test pandas         :    500000 -  . . . . .  -- 0.493   . . . . .  -- 0.499

当列表首先被打乱时,排序的代价变得明显——效率显著下降,@moooeeeep方法占主导地位,set &Dict方法相似,但表现较差:

Finding FIRST then ALL duplicates, single dupe of "n" included in randomised 1m element array
Test set len change :    500000 -  . . . . .  -- 0.321   . . . . .  -- 0.473
Test in dict        :    500000 -  . . . . .  -- 0.285   . . . . .  -- 0.360
Test in set         :    500000 -  . . . . .  -- 0.309   . . . . .  -- 0.365
Test sort/adjacent  :    500000 -  . . . . .  -- 0.756   . . . . .  -- 0.823
Test sort/groupby   :    500000 -  . . . . .  -- 1.459   . . . . .  -- 1.896
Test sort/izip      :    500000 -  . . . . .  -- 0.786   . . . . .  -- 0.845
Test sort/tee/izip  :    500000 -  . . . . .  -- 0.743   . . . . .  -- 0.804
Test moooeeeep      :    500000 -  . . . . .  -- 0.234   . . . . .  -- 0.311  *
Test iter*/sorted   :    500000 -  . . . . .  -- 0.776   . . . . .  -- 0.840
Test pandas         :    500000 -  . . . . .  -- 0.539   . . . . .  -- 0.540

我会用熊猫做这个,因为我经常用熊猫

import pandas as pd
a = [1,2,3,3,3,4,5,6,6,7]
vc = pd.Series(a).value_counts()
vc[vc > 1].index.tolist()

给了

[3,6]

可能不是很有效,但它肯定比许多其他答案的代码更少,所以我想我可以贡献一下

我必须这样做,因为我挑战自己不使用其他方法:

def dupList(oldlist):
if type(oldlist)==type((2,2)):
oldlist=[x for x in oldlist]
newList=[]
newList=newList+oldlist
oldlist=oldlist
forbidden=[]
checkPoint=0
for i in range(len(oldlist)):
#print 'start i', i
if i in forbidden:
continue
else:
for j in range(len(oldlist)):
#print 'start j', j
if j in forbidden:
continue
else:
#print 'after Else'
if i!=j:
#print 'i,j', i,j
#print oldlist
#print newList
if oldlist[j]==oldlist[i]:
#print 'oldlist[i],oldlist[j]', oldlist[i],oldlist[j]
forbidden.append(j)
#print 'forbidden', forbidden
del newList[j-checkPoint]
#print newList
checkPoint=checkPoint+1
return newList

所以你的样本工作如下:

>>>a = [1,2,3,3,3,4,5,6,6,7]
>>>dupList(a)
[1, 2, 3, 4, 5, 6, 7]

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

第三个接受答案的例子给出了一个错误的答案,并且没有试图给出重复的答案。下面是正确的版本:

number_lst = [1, 1, 2, 3, 5, ...]


seen_set = set()
duplicate_set = set(x for x in number_lst if x in seen_set or seen_set.add(x))
unique_set = seen_set - duplicate_set

这里有很多答案,但我认为这是一个相对易于阅读和理解的方法:

def get_duplicates(sorted_list):
duplicates = []
last = sorted_list[0]
for x in sorted_list[1:]:
if x == last:
duplicates.append(x)
last = x
return set(duplicates)

注:

  • 如果您希望保留重复计数,请取消强制转换
  • . .
  • 如果您更喜欢使用生成器,请将duplicates.append (x)替换为产生x和底部的return语句(您可以稍后强制转换为set)

下面是一个快速生成器,它使用dict将每个元素存储为一个带有布尔值的键,用于检查是否已经产生了重复项。

对于所有元素都是可哈希类型的列表:

def gen_dupes(array):
unique = {}
for value in array:
if value in unique and unique[value]:
unique[value] = False
yield value
else:
unique[value] = True


array = [1, 2, 2, 3, 4, 1, 5, 2, 6, 6]
print(list(gen_dupes(array)))
# => [2, 1, 6]

对于可能包含列表的列表:

def gen_dupes(array):
unique = {}
for value in array:
is_list = False
if type(value) is list:
value = tuple(value)
is_list = True


if value in unique and unique[value]:
unique[value] = False
if is_list:
value = list(value)


yield value
else:
unique[value] = True


array = [1, 2, 2, [1, 2], 3, 4, [1, 2], 5, 2, 6, 6]
print(list(gen_dupes(array)))
# => [2, [1, 2], 6]

在Python中,只需一次迭代就可以找到被愚弄的人,这是一个非常简单快速的方法:

testList = ['red', 'blue', 'red', 'green', 'blue', 'blue']


testListDict = {}


for item in testList:
try:
testListDict[item] += 1
except:
testListDict[item] = 1


print testListDict

输出内容如下:

>>> print testListDict
{'blue': 3, 'green': 1, 'red': 2}

这和更多在我的博客http://www.howtoprogramwithpython.com

这里有一个简洁明了的解决方案——

for x in set(li):
li.remove(x)


li = list(set(li))

使用熊猫:

>>> import pandas as pd
>>> a = [1, 2, 1, 3, 3, 3, 0]
>>> pd.Series(a)[pd.Series(a).duplicated()].values
array([1, 3, 3])

你可以使用iteration_utilities.duplicates:

>>> from iteration_utilities import duplicates


>>> list(duplicates([1,1,2,1,2,3,4,2]))
[1, 1, 2, 2]

或者如果你只想要一个副本,可以用iteration_utilities.unique_everseen组合:

>>> from iteration_utilities import unique_everseen


>>> list(unique_everseen(duplicates([1,1,2,1,2,3,4,2])))
[1, 2]

它也可以处理不可哈希的元素(但是以性能为代价):

>>> list(duplicates([[1], [2], [1], [3], [1]]))
[[1], [1]]


>>> list(unique_everseen(duplicates([[1], [2], [1], [3], [1]])))
[[1]]

这是只有少数其他方法可以处理的问题。

基准

我做了一个快速的基准测试,其中包含了这里提到的大部分(但不是全部)方法。

第一个基准测试只包含了很小范围的列表长度,因为一些方法具有O(n**2)行为。

在图表中,y轴代表时间,所以值越低越好。它还绘制了log-log,以便更好地可视化广泛的值范围:

enter image description here

删除O(n**2)方法,我在列表中做了另一个多达50万个元素的基准测试:

enter image description here

正如你所看到的,iteration_utilities.duplicates方法比任何其他方法都快,甚至连unique_everseen(duplicates(...))也比其他方法更快或同样快。

这里需要注意的另一件有趣的事情是,熊猫方法对于小列表非常慢,但可以轻松地竞争较长的列表。

然而,由于这些基准测试显示大多数方法的性能大致相同,所以使用哪一种并不重要(除了有O(n**2)运行时的3种方法)。

from iteration_utilities import duplicates, unique_everseen
from collections import Counter
import pandas as pd
import itertools


def georg_counter(it):
return [item for item, count in Counter(it).items() if count > 1]


def georg_set(it):
seen = set()
uniq = []
for x in it:
if x not in seen:
uniq.append(x)
seen.add(x)


def georg_set2(it):
seen = set()
return [x for x in it if x not in seen and not seen.add(x)]


def georg_set3(it):
seen = {}
dupes = []


for x in it:
if x not in seen:
seen[x] = 1
else:
if seen[x] == 1:
dupes.append(x)
seen[x] += 1


def RiteshKumar_count(l):
return set([x for x in l if l.count(x) > 1])


def moooeeeep(seq):
seen = set()
seen_add = seen.add
# adds all elements it doesn't know yet to seen and all other to seen_twice
seen_twice = set( x for x in seq if x in seen or seen_add(x) )
# turn the set into a list (as requested)
return list( seen_twice )


def F1Rumors_implementation(c):
a, b = itertools.tee(sorted(c))
next(b, None)
r = None
for k, g in zip(a, b):
if k != g: continue
if k != r:
yield k
r = k


def F1Rumors(c):
return list(F1Rumors_implementation(c))


def Edward(a):
d = {}
for elem in a:
if elem in d:
d[elem] += 1
else:
d[elem] = 1
return [x for x, y in d.items() if y > 1]


def wordsmith(a):
return pd.Series(a)[pd.Series(a).duplicated()].values


def NikhilPrabhu(li):
li = li.copy()
for x in set(li):
li.remove(x)


return list(set(li))


def firelynx(a):
vc = pd.Series(a).value_counts()
return vc[vc > 1].index.tolist()


def HenryDev(myList):
newList = set()


for i in myList:
if myList.count(i) >= 2:
newList.add(i)


return list(newList)


def yota(number_lst):
seen_set = set()
duplicate_set = set(x for x in number_lst if x in seen_set or seen_set.add(x))
return seen_set - duplicate_set


def IgorVishnevskiy(l):
s=set(l)
d=[]
for x in l:
if x in s:
s.remove(x)
else:
d.append(x)
return d


def it_duplicates(l):
return list(duplicates(l))


def it_unique_duplicates(l):
return list(unique_everseen(duplicates(l)))

基准1

from simple_benchmark import benchmark
import random


funcs = [
georg_counter, georg_set, georg_set2, georg_set3, RiteshKumar_count, moooeeeep,
F1Rumors, Edward, wordsmith, NikhilPrabhu, firelynx,
HenryDev, yota, IgorVishnevskiy, it_duplicates, it_unique_duplicates
]


args = {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(2, 12)}


b = benchmark(funcs, args, 'list size')


b.plot()

基准2

funcs = [
georg_counter, georg_set, georg_set2, georg_set3, moooeeeep,
F1Rumors, Edward, wordsmith, firelynx,
yota, IgorVishnevskiy, it_duplicates, it_unique_duplicates
]


args = {2**i: [random.randint(0, 2**(i-1)) for _ in range(2**i)] for i in range(2, 20)}


b = benchmark(funcs, args, 'list size')
b.plot()

免责声明

1这是来自我写的第三方库:iteration_utilities

通过检查出现的次数,简单地遍历列表中的每个元素,然后将它们添加到一个集,然后打印重复的元素。希望这能帮助到一些人。

myList  = [2 ,4 , 6, 8, 4, 6, 12];
newList = set()


for i in myList:
if myList.count(i) >= 2:
newList.add(i)


print(list(newList))
## [4 , 6]

我们可以使用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
def removeduplicates(a):
seen = set()


for i in a:
if i not in seen:
seen.add(i)
return seen


print(removeduplicates([1,1,2,2]))
没有转换为列表,可能最简单的方法是如下所示。 这可能在面试中有用,当他们要求不要使用sets

a=[1,2,3,3,3]
dup=[]
for each in a:
if each not in dup:
dup.append(each)
print(dup)

======= else获取唯一值和重复值的2个单独列表

a=[1,2,3,3,3]
uniques=[]
dups=[]


for each in a:
if each not in uniques:
uniques.append(each)
else:
dups.append(each)
print("Unique values are below:")
print(uniques)
print("Duplicate values are below:")
print(dups)

还有其他测试。当然要做……

set([x for x in l if l.count(x) > 1])

...代价太大了。使用下一个final方法大约快500倍(数组越长结果越好):

def dups_count_dict(l):
d = {}


for item in l:
if item not in d:
d[item] = 0


d[item] += 1


result_d = {key: val for key, val in d.iteritems() if val > 1}


return result_d.keys()

只有2个循环,没有非常昂贵的l.count()操作。

下面是一个比较方法的代码。代码如下,输出如下:

dups_count: 13.368s # this is a function which uses l.count()
dups_count_dict: 0.014s # this is a final best function (of the 3 functions)
dups_count_counter: 0.024s # collections.Counter

测试代码:

import numpy as np
from time import time
from collections import Counter


class TimerCounter(object):
def __init__(self):
self._time_sum = 0


def start(self):
self.time = time()


def stop(self):
self._time_sum += time() - self.time


def get_time_sum(self):
return self._time_sum




def dups_count(l):
return set([x for x in l if l.count(x) > 1])




def dups_count_dict(l):
d = {}


for item in l:
if item not in d:
d[item] = 0


d[item] += 1


result_d = {key: val for key, val in d.iteritems() if val > 1}


return result_d.keys()




def dups_counter(l):
counter = Counter(l)


result_d = {key: val for key, val in counter.iteritems() if val > 1}


return result_d.keys()






def gen_array():
np.random.seed(17)
return list(np.random.randint(0, 5000, 10000))




def assert_equal_results(*results):
primary_result = results[0]
other_results = results[1:]


for other_result in other_results:
assert set(primary_result) == set(other_result) and len(primary_result) == len(other_result)




if __name__ == '__main__':
dups_count_time = TimerCounter()
dups_count_dict_time = TimerCounter()
dups_count_counter = TimerCounter()


l = gen_array()


for i in range(3):
dups_count_time.start()
result1 = dups_count(l)
dups_count_time.stop()


dups_count_dict_time.start()
result2 = dups_count_dict(l)
dups_count_dict_time.stop()


dups_count_counter.start()
result3 = dups_counter(l)
dups_count_counter.stop()


assert_equal_results(result1, result2, result3)


print 'dups_count: %.3f' % dups_count_time.get_time_sum()
print 'dups_count_dict: %.3f' % dups_count_dict_time.get_time_sum()
print 'dups_count_counter: %.3f' % dups_count_counter.get_time_sum()

当使用toolz时:

from toolz import frequencies, valfilter


a = [1,2,2,3,4,5,4]
>>> list(valfilter(lambda count: count > 1, frequencies(a)).keys())
[2,4]

我进入这个讨论已经很晚了。尽管如此,我还是想用一句话来解决这个问题。因为这就是Python的魅力所在。 如果我们只是想把副本放到一个单独的列表(或任何集合)中,我建议这样做。假设我们有一个重复的列表,我们可以称它为'target'

    target=[1,2,3,4,4,4,3,5,6,8,4,3]

现在如果我们想要得到副本,我们可以使用下面的一行代码:

    duplicates=dict(set((x,target.count(x)) for x in filter(lambda rec : target.count(rec)>1,target)))

这段代码将把复制的记录作为键,并将其作为值放入字典'duplicate '中。“复制”字典将如下所示:

    {3: 3, 4: 4} #it saying 3 is repeated 3 times and 4 is 4 times

如果你只是想在一个列表中单独列出所有重复的记录,它的代码也更短:

    duplicates=filter(lambda rec : target.count(rec)>1,target)

输出将是:

    [3, 4, 4, 4, 3, 4, 3]

这在python 2.7中完美地工作。X +版本

方法1:

list(set([val for idx, val in enumerate(input_list) if val in input_list[idx+1:]]))

< >强劲的解释: [val for idx, val in enumerate(input_list) if val in input_list[idx+1:]]是一个列表推导式,它返回一个元素,如果该元素从当前位置存在,则在列表中返回索引 < p >的例子: input_list =[3 42 42岁,31日,31日,31日,31日,5日,6日6日6日6日6日,7日,42)< / p >

从列表42的第一个元素开始,索引为0,它检查元素42是否存在于input_list[1:]中(即从索引1到列表末尾) 因为42存在于input_list[1:]中,它将返回42.

然后它转到下一个索引为1的元素31,并检查元素31是否存在于input_list[2:]中(即从索引2到列表末尾), 因为31存在于input_list[2:]中,它将返回31

类似地,它遍历列表中的所有元素,只将重复/重复的元素返回到列表中。

然后,因为列表中有重复项,我们需要从每个重复项中选择一个,即从重复项中删除重复项,为此,我们调用python内置的名为set()的函数,它会删除重复项,

然后我们就得到了一个集合,而不是一个列表,因此为了将集合转换为列表,我们使用类型转换,list(),它将元素集转换为列表。

方法2:

def dupes(ilist):
temp_list = [] # initially, empty temporary list
dupe_list = [] # initially, empty duplicate list
for each in ilist:
if each in temp_list: # Found a Duplicate element
if not each in dupe_list: # Avoid duplicate elements in dupe_list
dupe_list.append(each) # Add duplicate element to dupe_list
else:
temp_list.append(each) # Add a new (non-duplicate) to temp_list


return dupe_list

< >强劲的解释: 首先,我们创建两个空列表。 然后继续遍历列表中的所有元素,以查看temp_list(最初为空)中是否存在该元素。如果它不在temp_list中,那么我们使用附加方法将它添加到temp_list

如果它已经存在于temp_list中,这意味着列表中的当前元素是重复的,因此我们需要使用附加方法将它添加到dupe_list中。

raw_list = [1,2,3,3,4,5,6,6,7,2,3,4,2,3,4,1,3,4,]


clean_list = list(set(raw_list))
duplicated_items = []


for item in raw_list:
try:
clean_list.remove(item)
except ValueError:
duplicated_items.append(item)




print(duplicated_items)
# [3, 6, 2, 3, 4, 2, 3, 4, 1, 3, 4]

基本上可以通过转换为set (clean_list)来删除重复项,然后迭代raw_list,同时删除干净列表中出现在raw_list中的每个item。如果没有找到item,则会捕获引发的ValueError异常,并将item添加到duplicated_items列表中。

如果需要重复项的索引,只需在列表中使用enumerate并使用索引。(for index, item in enumerate(raw_list):),这是更快和优化的大型列表(如数千+元素)

使用列表中的list.count()方法找出给定列表中的重复元素

arr=[]
dup =[]
for i in range(int(input("Enter range of list: "))):
arr.append(int(input("Enter Element in a list: ")))
for i in arr:
if arr.count(i)>1 and i not in dup:
dup.append(i)
print(dup)

为了好玩,只需要一行语句。

(lambda iterable: reduce(lambda (uniq, dup), item: (uniq, dup | {item}) if item in uniq else (uniq | {item}, dup), iterable, (set(), set())))(some_iterable)

我想在列表中找到重复项最有效的方法是:

from collections import Counter


def duplicates(values):
dups = Counter(values) - Counter(set(values))
return list(dups.keys())


print(duplicates([1,2,3,6,5,2]))

它对所有元素使用一次Counter,然后对所有唯一元素使用一次。用第二个减去第一个,只剩下重复的部分。

使用Set函数 如:- < / p >

arr=[1,4,2,5,2,3,4,1,4,5,2,3]
arr2=list(set(arr))
print(arr2)

输出:- [1,2,3,4,5]

  1. 使用array删除副本

如:-

arr=[1,4,2,5,2,3,4,1,4,5,2,3]
arr3=[]
for i in arr:
if(i not in arr3):
arr3.append(i)
print(arr3)

输出:

[1,4,2,5,3]

  1. 使用Lambda函数

如:-

rem_duplicate_func=lambda arr:set(arr)
print(rem_duplicate_func(arr))

输出:

{1,2,3,4,5}

  1. 从字典中删除重复值

如:-

dict1={
'car':["Ford","Toyota","Ford","Toyota"],
'brand':["Mustang","Ranz","Mustang","Ranz"] } dict2={} for key,value in dict1.items():
dict2[key]=set(value) print(dict2)

输出:

{“车”:{“丰田”、“福特”},“品牌”:{“主攻”、“野马”}}

  1. 对称差异-删除重复元素

如:-

set1={1,2,4,5}
set2={2,1,5,7}
rem_dup_ele=set1.symmetric_difference(set2)
print(rem_dup_ele)

输出:

{4 7}

如果你不关心自己编写算法或使用库,Python 3.8一行代码:

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


res = [(x, count) for x, g in groupby(sorted(l)) if (count := len(list(g))) > 1]


print(res)

打印项目和计数:

[(1, 2), (2, 2), (5, 4)]

groupby接受一个分组函数,因此您可以以不同的方式定义分组,并根据需要返回额外的Tuple字段。

我没有看到一个纯粹使用迭代器的解决方案,所以我们开始吧

这需要对列表进行排序,这可能是这里的缺点。

a = [1,2,3,2,1,5,6,5,5,5]
a.sort()
set(map(lambda x: x[0], filter(lambda x: x[0] == x[1], zip(a, a[1:]))))


{1, 2, 5}

你可以用这段代码轻松检查你的机器有多快,有一百万潜在的重复:

首先生成数据

import random
from itertools import chain
a = list(chain(*[[n] * random.randint(1, 2) for n in range(1000000)]))

并运行测试:

set(map(lambda x: x[0], filter(lambda x: x[0] == x[1], zip(a, a[1:]))))

不用说,这个解决方案只在列表已经排序的情况下才有效。

试试这个检查副本

>>> def checkDuplicate(List):
duplicate={}
for i in List:
## checking whether the item is already present in dictionary or not
## increasing count if present
## initializing count to 1 if not present


duplicate[i]=duplicate.get(i,0)+1


return [k for k,v in duplicate.items() if v>1]


>>> checkDuplicate([1,2,3,"s",1,2,3])
[1, 2, 3]

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

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

排序会把副本放在一起,所以它们都在偶数下标和奇数下标处。唯一值只有在奇数索引的偶数处,而不是两个都有。所以偶数下标值和奇数下标值的交集就是重复项。

< p >基准测试结果: # EYZ0 < / p >

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

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

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

在没有任何python数据结构的帮助下,你可以简单地尝试下面的代码。这将工作于寻找重复的各种输入,如字符串,列表等。

# finding duplicates in unsorted an array
def duplicates(numbers):
store=[]
checked=[]
for i in range(len(numbers)):
counter =1
for j in range(i+1,len(numbers)):
if numbers[i] not in checked and numbers[j]==numbers[i] :
counter +=1
if counter > 1 :
store.append(numbers[i])
checked.append(numbers[i])
return store


print(duplicates([1,2,2,3,3,3,4,4,5]))  # output:  [2, 3, 4]
print(duplicates("madam"))              # output:  ['m', 'a']

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

>>> 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]
>>>

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

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)
some_list = ['a', 'b', 'c', 'b', 'd', 'm', 'n', 'n']
some_dictionary = {}


for element in some_list:
if element not in some_dictionary:
some_dictionary[element] = 1
else:
some_dictionary[element] += 1


for key, value in some_dictionary.items():
if value > 1:
print(key, end = ' ')


# another way
duplicates = []


for x in some_list:
if some_list.count(x) > 1 and x not in duplicates:
duplicates.append(x)


print()
print(duplicates)

来源:# EYZ0

另一种解决方案如下所示,不使用任何集合库。

a = [1,2,3,5,4,6,4,21,4,6,3,32,5,2,23,5]
duplicates = []


for i in a:
if a.count(i) > 1 and i not in duplicates:
duplicates.append(i)


print(duplicates)

输出是[2, 3, 5, 4, 6]

我注意到大多数解决方案的复杂度为O(n * n),对于大型列表来说非常缓慢。所以我想分享一下我写的函数,它支持整数或字符串,在最好的情况下是O(n)。对于一个包含10万个元素的列表,最上面的解决方案需要超过30秒,而我的解决方案只需0.12秒

def get_duplicates(list1):
'''Return all duplicates given a list. O(n) complexity for best case scenario.
input: [1, 1, 1, 2, 3, 4, 4]
output: [1, 1, 4]
'''
dic = {}
for el in list1:
try:
dic[el] += 1
except:
dic[el] = 1
dupes = []
for key in dic.keys():
for i in range(dic[key] - 1):
dupes.append(key)
return dupes




list1 = [1, 1, 1, 2, 3, 4, 4]
> print(get_duplicates(list1))
[1, 1, 4]

或者获得唯一的副本:

> print(list(set(get_duplicates(list1))))
[1, 4]

为了实现这个问题,我们可以使用多种不同的方法来解决它,这两种是常见的解决方案,但在实际场景中实现它们时,我们还必须考虑时间复杂性。

import random
import time


dupl_list = [random.randint(1,1000) for x in range(500)]
print("List with duplicate integers")
print (dupl_list)




#Method 1
print("******************Method 1 *************")


def Repeat_num(x):
_size = len(x)
repeated = []
for i in range(_size):
# print(i)
k = i + 1
for j in range(k, _size):
# print(j)
if x[i] == x[j] and x[i] not in repeated:
repeated.append(x[i])
return repeated


start = time.time()
print(Repeat_num(dupl_list))
end = time.time()
print("The time of execution of above program is :",(end-start) * 10**3, "ms")


print("***************Method 2****************")


#method 2 - using count()
def repeast_count(dup_list):
new = []
for a in dup_list:
# print(a)
# checking the occurrence of elements
n = dup_list.count(a)
# if the occurrence is more than
# one we add it to the output list
if n > 1:
if new.count(a) == 0:  # condition to check
new.append(a)
return new




start = time.time()
print(repeast_count(dupl_list))
end = time.time()
print("The time of execution of above program is :",(end-start) * 10**3, "ms")

# #输出示例:

List with duplicate integers
[5, 45, 28, 81, 32, 98, 8, 83, 47, 95, 41, 49, 4, 1, 85, 26, 38, 82, 54, 11]
******************Method 1 *************
[]
The time of execution of above program is : 1.1069774627685547 ms
***************Method 2****************
[]
The time of execution of above program is : 0.1881122589111328 ms

对于一般的理解,方法1是好的,但是对于真正的实现,我更喜欢方法2,因为它比方法1花费的时间更少。