[英]How to remove `duplicates' in list of instances
我有某个类的实例列表。 该列表包含“重复项”,即重复项具有完全相同的属性。 我想从此列表中删除重复项。
我可以通过使用以下命令检查两个实例是否共享相同的属性
class MyClass:
def __eq__(self, other) :
return self.__dict__ == other.__dict__
我当然可以遍历整个实例列表,然后逐个元素地比较它们以删除重复项,但是我想知道是否还有更Python的方法来做到这一点,最好使用in运算符+列表理解。
set
s(无顺序) 集合不能包含重复的元素。 list(set(content))
将删除列表中的重复数据。 这并不是效率太低,并且可能是实现它的更好方法之一:P但是,您将需要为类定义__hash__
函数,该函数对于相等的元素必须相同,对于不相等的元素必须不同,这样才能起作用。 请注意, hash
值必须遵守上述规则,但是在运行之间可能会发生变化而不会引起问题。
index
功能(稳定顺序) 您可以执行lambda l: [l[index] for index in range(len(l)) if index == l.index(l[index])]
。 这只会保留列表中的第一个元素。
in
运算符中(稳定的顺序) def uniquify(content):
result = []
for element in content:
if element not in result:
result.append(element)
return result
除非将元素添加到输出列表中,否则它将继续将元素添加到输出列表中。
关于固定方法的更多信息。 您可以通过委派给元组的哈希来安全地实现哈希-只需对要查看的所有属性的元组进行哈希处理即可。 您还需要定义行为正确的__eq__
。
class MyClass:
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def __eq__(self, other):
return (self.a, self.b, self.c) == (other.a, other.b, other.c)
def __hash__(self):
return hash((self.a, self.b, self.c))
def __repr__(self):
return "MyClass({!r}, {!r}, {!r})".format(self.a, self.b, self.c)
当您进行大量的元组构造时,您可以使您的类可迭代:
def __iter__(self):
return iter((self.a, self.b, self.c))
这使您可以对self
调用tuple
,而不必费力地执行.a, .b, .c
等。
然后,您可以执行以下操作:
def unordered_elim(l):
return list(set(l))
如果要保留顺序,可以改用OrderedDict
:
from collections import OrderedDict
def ordered_elim(l):
return list(OrderedDict.fromkeys(l).keys())
这应该比使用in
或index
更快,同时仍保留顺序。 您可以像这样测试它:
data = [MyClass("this", "is a", "duplicate"),
MyClass("first", "unique", "datum"),
MyClass("this", "is a", "duplicate"),
MyClass("second", "unique", "datum")]
print(unordered_elim(data))
print(ordered_elim(data))
输出如下:
[MyClass('first', 'unique', 'datum'), MyClass('second', 'unique', 'datum'), MyClass('this', 'is a', 'duplicate')]
[MyClass('this', 'is a', 'duplicate'), MyClass('first', 'unique', 'datum'), MyClass('second', 'unique', 'datum')]
注意:如果您的任何属性都不是可哈希的,那么它将无法正常工作,您要么需要解决它(将列表更改为元组),要么使用像in
那样的慢速n ^ 2
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.