我有一个特定类的实例列表。此列表包含`duplicates',在重复项共享完全相同的属性的意义上。我想从此列表中删除重复项。
我可以使用
检查两个实例是否共享相同的属性class MyClass:
def __eq__(self, other) :
return self.__dict__ == other.__dict__
我当然可以迭代整个实例列表并逐个元素地比较它们以删除重复项,但我想知道是否有更多的pythonic方法来执行此操作,最好使用in运算符+列表理解。
答案 0 :(得分:4)
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
这将继续将元素附加到输出列表,除非它们已经在输出列表中。
答案 1 :(得分:2)
关于设定方法的更多信息。您可以通过委托给元组的哈希来安全地实现哈希 - 只需哈希一个您想要查看的所有属性的元组。您还需要定义一个行为正常的__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))
这使您可以在tuple
上致电self
而不是费力地执行.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')]
请注意,如果您的任何属性无法播放,则无法正常工作,并且您需要解决此问题(将列表更改为元组)或使用缓慢的{{ {1}}类似于n ^ 2
。