如何在列表中找到重复项并使用它们创建另一个列表?
- 2024-11-28 08:37:00
- admin 原创
- 12
问题描述:
如何在整数列表中找到重复项并创建另一个重复项列表?
解决方案 1:
要删除重复项,请使用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)
(setadd()
方法总是返回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)]
如果列表元素不可哈希,则不能使用集合/字典,而必须采用二次时间解决方案(将每个元素与每个元素进行比较)。例如:
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]]
解决方案 2:
一个非常简单的解决方案,但复杂度为 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])
解决方案 3:
您不需要计数,只需要知道该项目是否之前被看到过。改编了该答案来解决这个问题:
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 时排名也会略有变化。最有趣的是,基于计数器的方法从 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
解决方案 4:
您可以使用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 轴表示时间,因此值越低越好。它还以对数对数形式绘制,以便可以更好地直观地显示各种值:
删除这些O(n**2)
方法后,我对列表中多达 50 万个元素进行了另一项基准测试:
如您所见,该iteration_utilities.duplicates
方法比任何其他方法都快,甚至链接也unique_everseen(duplicates(...))
比其他方法更快或同样快。
这里需要注意的另一个有趣的事情是,对于小列表,pandas 方法非常慢,但对于较长的列表却可以轻松竞争。
然而,正如这些基准测试显示,大多数方法的性能大致相同,所以使用哪一种方法并不重要(除了有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
。
解决方案 5:
我在研究相关内容时遇到了这个问题 - 并且想知道为什么没有人提供基于生成器的解决方案? 解决这个问题的方法是:
>>> print list(getDupes_9([1,2,3,2,1,5,6,5,5,5]))
[1, 2, 5]
我担心可扩展性,因此测试了几种方法,包括在小列表上运行良好的简单项目,但随着列表变大而扩展变得可怕(注意 - 最好使用 timeit,但这只是说明性的)。
我加入了@moooeeeep 进行比较(它的速度非常快:如果输入列表完全随机,则速度最快)和 itertools 方法,对于大多数排序列表,该方法的速度甚至更快……现在包括来自@firelynx 的 pandas 方法——速度慢,但不是太慢,而且很简单。注意 - 在我的计算机上,对于大型、大多数排序列表,sort/tee/zip 方法始终是最快的,而对于随机播放列表,moooeeeep 是最快的,但您的里程可能会有所不同。
优点
使用相同的代码可以非常快速简单地测试“任何”重复项
假设
重复项只需报告一次
重复的订单不需要保留
重复项可能位于列表中的任何地方
最快的解决方案,100 万个条目:
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
“所有重复项”测试的结果是一致的,在这个数组中找到“第一个”重复项,然后找到“所有”重复项:
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
当首先对列表进行混洗时,排序的代价就变得显而易见 - 效率明显下降,并且 @moooeeeeep 方法占主导地位,而 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
解决方案 6:
使用熊猫:
>>> import pandas as pd
>>> a = [1, 2, 1, 3, 3, 3, 0]
>>> pd.Series(a)[pd.Series(a).duplicated()].values
array([1, 3, 3])
解决方案 7:
这是一个简洁明了的解决方案 -
for x in set(li):
li.remove(x)
li = list(set(li))
解决方案 8:
如果你不想编写自己的算法或使用库,则可以使用 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
根据需要返回其他字段。
解决方案 9:
collections.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]
解决方案 10:
我认为在列表中查找重复项的最有效方法是:
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
所有元素使用一次,然后对所有唯一元素使用一次。用第二个减去第一个将只留下重复项。
解决方案 11:
我会用熊猫来做这个,因为我经常使用熊猫
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]
可能效率不高,但肯定比其他答案的代码要少,所以我想我可以做出贡献
解决方案 12:
如何简单地循环遍历列表中的每个元素,检查出现的次数,然后将它们添加到一个集合中,然后打印重复项。希望这对某些人有所帮助。
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]
解决方案 13:
我们可以使用itertools.groupby
来查找所有有重复的项目:
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
解决方案 14:
无需转换为列表,最简单的方法可能如下所示。
这可能在面试时很有用,因为他们要求不要使用集合
a=[1,2,3,3,3]
dup=[]
for each in a:
if each not in dup:
dup.append(each)
print(dup)
=======否则获取 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)
解决方案 15:
尽管它的复杂度为 O(n log n),但它似乎具有一定的竞争力,请参阅下面的基准测试。
a = sorted(a)
dupes = list(set(a[::2]) & set(a[1::2]))
排序将重复项放在一起,因此它们既位于偶数索引处,又位于奇数索引处。唯一值只能位于偶数索引处或奇数索引处,不能同时位于两者处。因此,偶数索引值和奇数索引值的交集就是重复项。
基准测试结果:
这使用MSeifert 的基准,但只使用已接受答案(georgs)、最慢的解决方案、最快的解决方案(排除,it_duplicates
因为它不会唯一化重复项)和我的解决方案。否则它会太拥挤,颜色太相似。
第一行可能是a.sort()
如果我们被允许修改给定的列表,那会快一点。但基准测试多次重复使用同一个列表,因此修改它会扰乱基准测试。
而且显然set(a[::2]).intersection(a[1::2])
不会创建第二组并且速度会更快一些,但是,嗯,它也会更长一些。
解决方案 16:
被接受答案的第三个示例给出了错误的答案,并且没有尝试给出重复的答案。以下是正确的版本:
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
解决方案 17:
有点晚了,但可能对某些人有帮助。对于较大的列表,我发现这对我有用。
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]
仅显示所有重复项并保留顺序。
解决方案 18:
其中一些解决方案要么是二次复杂度,要么是冗长的,要么需要第三方库。
这是一个简单的两行答案,使用“可见集”策略,可以保持时间复杂度线性,同时仅使内存加倍。
def duplicates(array):
seen = set()
return { val for val in array if (val in seen or seen.add(val)) }
---
duplicates(["a", "b", "c", "a", "d"])
> {'a'}
工作原理
val in seen
如果包含值,则为真seen
,因此它将得出返回的理解中的元素否则,
or seen.add(val)
将元素添加到可见集合(不包括在列表中,因为它返回在此上下文中None
表达的内容False
。)所有内容都包裹在集合理解中,确保我们只返回每个重复元素一次。
解决方案 19:
在 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
解决方案 20:
我参加这个讨论的时间很晚。尽管如此,我还是想用一行代码来解决这个问题。因为这就是 Python 的魅力所在。如果我们只想将重复项放入单独的列表(或任何集合)中,我建议按如下方式操作。假设我们有一个重复的列表,我们可以将其称为“目标”
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)))
此代码将重复的记录作为键并将计数作为值放入字典“duplicates”中。“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 + 版本中完美运行
解决方案 21:
方法 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:]] 是列表推导,如果从列表中的当前位置(索引)存在相同的元素,则返回一个元素。
例如:input_list = [42,31,42,31,3,31,31,5,6,6,6,6,6,7,42]
从列表中的第一个元素 42(索引为 0)开始,检查元素 42 是否存在于 input_list[1:] 中(即从索引 1 到列表末尾)因为 42 存在于 input_list[1:] 中,所以它将返回 42。
然后它转到索引为 1 的下一个元素 31,并检查元素 31 是否存在于 input_list[2:] 中(即从索引 2 到列表末尾),因为 31 存在于 input_list[2:] 中,所以它将返回 31。
类似地,它会遍历列表中的所有元素,并且只将重复的元素返回到列表中。
然后因为我们有重复项,所以在列表中,我们需要从每个重复项中选择一个,即在重复项中删除重复项,为此,我们调用一个名为 set() 的 python 内置函数,它会删除重复项,
然后我们剩下了一个集合,而不是一个列表,因此要从集合转换为列表,我们使用类型转换,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 中不存在,则我们使用append方法将其添加到 temp_list 中。
如果它已经存在于 temp_list 中,则意味着列表的当前元素是重复的,因此我们需要使用append方法将其添加到 dupe_list 中。
解决方案 22:
另一个解决方案如下,不使用任何集合库。
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]
解决方案 23:
还有一些其他测试。当然要做……
set([x for x in l if l.count(x) > 1])
...成本太高。使用下一个最终方法大约快 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()
解决方案 24:
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
,同时删除item
干净列表中出现的 中的每个raw_list
。如果item
未找到 ,ValueError
则捕获引发的异常并将item
添加到duplicated_items
列表中。
如果需要重复项目的索引,只需enumerate
列出列表并使用索引即可。(for index, item in enumerate(raw_list):
)它更快并且针对大型列表(如数千个元素)进行了优化
解决方案 25:
使用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)
解决方案 26:
单行,为了好玩,并且只需要一个语句。
(lambda iterable: reduce(lambda (uniq, dup), item: (uniq, dup | {item}) if item in uniq else (uniq | {item}, dup), iterable, (set(), set())))(some_iterable)
解决方案 27:
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)
解决方案 28:
这里有很多答案,但我认为这是一种相对易读且易于理解的方法:
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)替换为Yield x并在底部添加 return 语句(您可以稍后转换为 set)
解决方案 29:
这是一个快速生成器,它使用字典将每个元素存储为键,并使用布尔值来检查是否已产生重复项。
对于所有元素均为可哈希类型的列表:
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]
解决方案 30:
使用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]
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 项目管理必备:盘点2024年13款好用的项目管理软件