2017-10-04 70 views
1

我有一个特定类的实例列表。该列表包含“重复”,意思是重复共享完全相同的属性。我想从此列表中删除重复项。如何删除实例列表中的“重复项”

我可以检查两个实例是否使用

class MyClass: 

    def __eq__(self, other) : 
     return self.__dict__ == other.__dict__ 

当然,我可以遍历实例的整个列表,并通过元素比较它们元素删除重复共享相同的属性,但我不知道是否有是一个更pythonic的方式来做到这一点,最好使用in运算符+列表理解。

+7

你可以让它们变成可散列的,然后使用'set'来消除重复项。 – vaultah

+1

注意:set方法不会保留你列表中的任何顺序。 –

+0

什么版本的Python? –

回答

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

更多关于设置的方法。您可以通过委托给元组的散列来安全地实现散列 - 只需散列您想要查看的所有属性的元组即可。您还需要定义行为正确的__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)) 

这使您可以致电selftuple,而不是费力地做.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()) 

这应该是比使用inindex,同时仍保留排序更快。您可以测试它是这样的:

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')] 

NB,如果你的任何属性都没有哈希的,这是行不通的,而你要么需要解决它(将列表更改为元组)或使用像in这样的缓慢的n^2方法。

+0

@ZachGates我不确定我的理解 - 就我而言,MyClass(1,2,3)!= MyClass(3,2,1)'(这也是OP所暗示的 - 他们将拥有一个不同的'dict'。)。至于'hash(self)== hash(other)' - 我们需要'__eq__'的全部原因是为了消除散列冲突。 –