2017-06-14 4 views
1

Say IPython: Wie du Dubletten in Listen nach Objektattributen filtern kannst?

class a: 
    b = 1 
thing = a() 
thing2 = a() 
thing3 = a() 
thing3.b = 2 
lst = [thing,thing2,thing3] 

haben Und ich möchte etwas wie folgt aus:

lst = filter_out(obj.b==obj2.b,lst) 

Ergebnis (die Objekte mit demselben Attribut gefiltert, so dass nur noch einer übrig ist):

[thing2,thing3]

Wie kann dies erreicht werden? Soweit ich weiß, würde der Lambda-Filter nicht funktionieren, um zwei Objekte in einer Liste zu vergleichen.

+2

Sollte die Antwort nicht '[Sache, Sache2]' sein? –

+1

'Class' ist eine ungültige Syntax. Es sollte "Klasse" sein. –

+0

@ WillemVanOnsem Ich möchte die duplizierten löschen, der Filter Teil war ein bisschen verwirrend, so änderte ich das – Pear

Antwort

2

Verwenden Sie ein Wörterbuch, um Objekte anhand ihres Attributs b zuzuordnen. Da das Diktat zweimal keine b enthalten kann, sind die Werte des Diktats Ihre einzigartigen Elemente.

>>> unique = {} 
>>> for x in lst: 
...  unique[x.b] = x 
... 
>>> list(unique.values()) 
[<__main__.a object at 0xb724cfcc>, <__main__.a object at 0xb724cfec>] 

Je nachdem, ob Sie das erste oder das letzte Einzelstück behalten möchten, entweder vorhandene Werte überschrieben werden (wie im obigen Code) oder fügen Sie eine if x.b not in unique Prüfung vor die Elemente hinzufügen.

+0

Oder, wenn Sie nicht überschreiben wollen, tun Sie 'unique.setdefault (xb, x) ' – Artyer

0

können Sie verwenden auch, groupby von itertools Modul, wie in diesem Beispiel:

from itertools import groupby 

class A: 
    b = 1 

thing = A() 
thing2 = A() 
thing3 = A() 
thing3.b = 2 
lst = [thing, thing2, thing3] 
# For testing purpose 
dct_id = {id(thing): "thing", id(thing2): "thing2", id(thing3): "thing3"} 
# groupping based on each object's b value 
sub = [list(v)[-1] for _, v in groupby(lst, lambda x: x.b)] 
# check the groupped objects by their id 
for k in sub: 
    print(dct_id[id(k)]) 

Ausgang:

thing2 
thing3 

Edit: Dank @ tobias_k Kommentar

Wenn wir haben diese Art von Objekten:

thing = A() 
thing2 = A() 
thing3 = A() 
thing2.b = 2 
lst = [thing, thing2, thing3] 

Um schlechte Ergebnisse zu vermeiden, müssen wir sort lst durch den Wert des Objekts b. So wird sub werden:

sub = [list(v)[-1] for _, v in groupby(sorted(lst, key=lambda x: x.b), lambda x: x.b)] 

Und den gleichen Test zu wiederholen wir haben:

thing3 
thing2 

Ps: es besser ist, sub Liste in jedem Fall zu sortieren, um schlechte Ergebnisse zu vermeiden.

+1

Versuchen Sie das gleiche mit 'ding2.b = 2' anstelle von' thing3.b = 2'. Dies funktioniert nur, wenn Elemente mit demselben "Schlüssel" -Wert nebeneinander liegen. –

+0

@tobias_k Guter Punkt! Also hier in diesem Fall muss ich 'lst' basierend auf dem b-Wert des Objekts sortieren. Siehe mein letztes Update. –

Verwandte Themen