我如何检查一个列表是否有任何重复,并返回一个没有重复的新列表?
当前回答
在这个答案中,将有两个部分:两个唯一的解,和一个特定解的速度图。
删除重复项
这些答案大多只删除可哈希的重复项,但这个问题并不意味着它不需要可哈希项,这意味着我将提供一些不需要可哈希项的解决方案。
集合。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
(放大)
其他回答
我的列表中有一个字典,所以我不能使用上面的方法。我得到了错误:
TypeError: unhashable type:
如果你关心顺序和/或某些项是不可散列的。那么你可能会发现这个很有用:
def make_unique(original_list):
unique_list = []
[unique_list.append(obj) for obj in original_list if obj not in unique_list]
return unique_list
有些人可能认为带副作用的列表理解不是一个好的解决方案。这里有一个替代方案:
def make_unique(original_list):
unique_list = []
map(lambda x: unique_list.append(x) if (x not in unique_list) else False, original_list)
return unique_list
您可以通过使用集合简单地做到这一点。
步骤1:获取列表的不同元素 Step2获取列表的公共元素 3 .结合
In [1]: a = ["apples", "bananas", "cucumbers"]
In [2]: b = ["pears", "apples", "watermelons"]
In [3]: set(a).symmetric_difference(b).union(set(a).intersection(b))
Out[3]: {'apples', 'bananas', 'cucumbers', 'pears', 'watermelons'}
def remove_duplicates(A):
[A.pop(count) for count,elem in enumerate(A) if A.count(elem)!=1]
return A
用于删除重复项的列表推导
它需要安装一个第三方模块,但包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的作者。
这是一行代码:list(set(source_list))就可以了。
集合是不可能有重复的东西。
更新:一个保持顺序的方法有两行:
from collections import OrderedDict
OrderedDict((x, True) for x in source_list).keys()
这里我们使用OrderedDict记住键的插入顺序,并且在更新特定键上的值时不更改它。我们插入True作为值,但我们可以插入任何值,只是不使用值。(set的工作原理也很像一个忽略值的字典。)
推荐文章
- 证书验证失败:无法获得本地颁发者证书
- 当使用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中获得所有直接子目录