我如何检查一个列表是否有任何重复,并返回一个没有重复的新列表?
当前回答
它需要安装一个第三方模块,但包iteration_utilities包含一个unique_everseen1函数,可以删除所有重复的同时保留顺序:
>>> from iteration_utilities import unique_everseen
>>> list(unique_everseen(['a', 'b', 'c', 'd'] + ['a', 'c', 'd']))
['a', 'b', 'c', 'd']
如果你想避免列表添加操作的开销,你可以使用itertools。链:
>>> from itertools import chain
>>> list(unique_everseen(chain(['a', 'b', 'c', 'd'], ['a', 'c', 'd'])))
['a', 'b', 'c', 'd']
unique_everseen也适用于列表中有不可哈希项(例如列表)的情况:
>>> from iteration_utilities import unique_everseen
>>> list(unique_everseen([['a'], ['b'], 'c', 'd'] + ['a', 'c', 'd']))
[['a'], ['b'], 'c', 'd', 'a']
然而,这将比项目是可哈希的(多)慢。
1披露:我是iteration_utilities-library的作者。
其他回答
您可以使用以下函数:
def rem_dupes(dup_list):
yooneeks = []
for elem in dup_list:
if elem not in yooneeks:
yooneeks.append(elem)
return yooneeks
例子:
my_list = ['this','is','a','list','with','dupicates','in', 'the', 'list']
用法:
rem_dupes(my_list)
[‘这个’,‘是’,‘“,“列表”,“与”,“dupicates”,“在”,“的”)
Test = [1,8,2,7,3,4,5,1,2,3,6]
Test.sort()
i=1
while i< len(Test):
if Test[i] == Test[i-1]:
Test.remove(Test[i])
i= i+1
print(Test)
def remove_duplicates(A):
[A.pop(count) for count,elem in enumerate(A) if A.count(elem)!=1]
return A
用于删除重复项的列表推导
在这个答案中,将有两个部分:两个唯一的解,和一个特定解的速度图。
删除重复项
这些答案大多只删除可哈希的重复项,但这个问题并不意味着它不需要可哈希项,这意味着我将提供一些不需要可哈希项的解决方案。
集合。Counter是标准库中的一个功能强大的工具,可以完美地实现这一点。只有另一种解决方案里面有Counter。然而,该解决方案也仅限于可哈希键。
为了在Counter中允许不可哈希键,我创建了一个Container类,它将尝试获取对象的默认哈希函数,但如果失败,它将尝试其标识函数。它还定义了一个eq和一个散列方法。这应该足以在我们的解决方案中允许不可散列项。不可哈希对象将被视为可哈希对象。但是,这个哈希函数对不可哈希对象使用identity,这意味着两个相等的不可哈希对象将不起作用。我建议您重写它,并将其更改为使用等效可变类型的哈希(例如,如果my_list是一个列表,则使用hash(tuple(my_list))。
我也得到了两个解。另一个解决方案是保持条目的顺序,使用OrderedDict和Counter的子类,命名为'OrderedCounter'。下面是函数:
from collections import OrderedDict, Counter
class Container:
def __init__(self, obj):
self.obj = obj
def __eq__(self, obj):
return self.obj == obj
def __hash__(self):
try:
return hash(self.obj)
except:
return id(self.obj)
class OrderedCounter(Counter, OrderedDict):
'Counter that remembers the order elements are first encountered'
def __repr__(self):
return '%s(%r)' % (self.__class__.__name__, OrderedDict(self))
def __reduce__(self):
return self.__class__, (OrderedDict(self),)
def remd(sequence):
cnt = Counter()
for x in sequence:
cnt[Container(x)] += 1
return [item.obj for item in cnt]
def oremd(sequence):
cnt = OrderedCounter()
for x in sequence:
cnt[Container(x)] += 1
return [item.obj for item in cnt]
Remd为非有序排序,oremd为有序排序。你可以清楚地看出哪个更快,但我还是会解释的。非有序排序稍微快一些,因为它不存储条目的顺序。
现在,我还想展示每个答案的速度比较。我现在就做。
哪个函数是最快的?
为了去除重复,我从几个答案中收集了10个函数。我计算了每个函数的速度,并使用matplotlib.pyplot将其放入一个图形中。
我把它分成三轮画图。hashable是任何可以哈希的对象,unhashable是任何不能哈希的对象。有序序列是保持有序的序列,无序序列不保持有序。现在,这里有更多的术语:
Unordered Hashable适用于任何删除重复项的方法,它不一定要保持顺序。它不需要为不可hashables工作,但它可以。
Ordered Hashable适用于任何保持列表中元素顺序的方法,但它不一定适用于unhashables,但它可以。
Ordered Unhashable是任何保持列表中项目顺序的方法,适用于unhashables。
y轴是花费的秒数。
x轴是函数作用的数字。
我用以下理解为无序哈希和有序哈希生成序列:[list(range(x)) + list(range(x)) for x in range(0,1000,10)]
对于有序的不可哈希对象:[[list(range(y)) + list(range(y)) For y in range(x)] For x in range(0,1000,10)]
请注意,在范围内有一个步骤,因为如果没有它,这将花费10倍的时间。也因为在我个人看来,我认为它可能看起来更容易阅读。
还要注意,图例上的键是我试图猜测的函数实现中最重要的部分。至于哪个功能是最好的还是最差的呢?图表说明了一切。
解决了这个问题,下面是图表。
无序Hashables
(放大)
命令Hashables
(放大)
命令Unhashables
(放大)
这里有一个例子,返回没有重复的列表,保持顺序。不需要任何外部导入。
def GetListWithoutRepetitions(loInput):
# return list, consisting of elements of list/tuple loInput, without repetitions.
# Example: GetListWithoutRepetitions([None,None,1,1,2,2,3,3,3])
# Returns: [None, 1, 2, 3]
if loInput==[]:
return []
loOutput = []
if loInput[0] is None:
oGroupElement=1
else: # loInput[0]<>None
oGroupElement=None
for oElement in loInput:
if oElement<>oGroupElement:
loOutput.append(oElement)
oGroupElement = oElement
return loOutput
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用pip3安装包时,“Python中的ssl模块不可用”
- 无法切换Python与pyenv
- Python if not == vs if !=
- 如何从scikit-learn决策树中提取决策规则?
- 为什么在Mac OS X v10.9 (Mavericks)的终端中apt-get功能不起作用?
- 将旋转的xtick标签与各自的xtick对齐
- 为什么元组可以包含可变项?
- 如何合并字典的字典?
- 如何创建类属性?
- 不区分大小写的“in”
- 在Python中获取迭代器中的元素个数
- 解析日期字符串并更改格式
- 使用try和。Python中的if
- 如何在Python中获得所有直接子目录