2017-10-04 91 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__'的全部原因是爲了消除散列衝突。 –