2013-06-03 11 views
7

Ich habe eine Liste von Instanzen aus derselben Klasse, und ich möchte meine Liste basierend auf einer Eigenschaft in der Klasse unterscheiden. Was ist der pythischste Weg, dies zu erreichen? HierWie erstelle ich eine Liste in Python basierend auf einer Eigenschaft der Klasse in der Liste?

ist ein Beispielcode:

#!/usr/bin/python 
#-*- coding:utf-8 -*- 

class MyClass(object): 
    def __init__(self, classId, tag): 
     self.classId = classId 
     self.tag = tag 

myList = [] 

myInstance1 = MyClass(1, "ABC") 
myInstance2 = MyClass(2, "DEF") 
myInstance3 = MyClass(3, "DEF") 

myList.append(myInstance1) 
myList.append(myInstance3) # note that the order is changed deliberately 
myList.append(myInstance2) 

Wenn ich meine Liste wollen jetzt sortieren basierend auf einer der Eigenschaften in MyClass, ich es in der Regel nur mit Schlüssel sortieren, und stellen Sie die Taste, um einen Lambda-Ausdruck mit - wie folgt aus:

myList.sort(key=lambda x: x.classId) 
for x in myList: 
    print x.classId 

$ python ./test.py 
1 
2 
3 

Ist es möglich, ein ähnliches Verfahren (Lambda, Karte oder ähnliches) zu verwenden, die Liste verschiedenen basierend auf der „Tag“ Eigenschaft zu machen? Ist dies, wenn dies möglich ist, der "pythischste" Weg, um eine Liste basierend auf einer Eigenschaft einer Klasse in dieser Liste eindeutig zu machen?

ich bereits versucht hat, sowohl SO und Google zu diesem Thema für Themen suchen, aber alle Ergebnisse, die ich mit einfachen Listen behandelt gefunden, die nur einen numerischen Wert enthalten ist und nicht ein benutzerdefiniertes Objekt ..

Antwort

6

Angenommen, die Eigenschaft, die Sie wollen auf Schlüssel ist unveränderlich, können Sie eine dict verwenden:

d = {} 
for x in xs: 
    d[x.tag] = x 

Jetzt enthält d einen einzigen x pro tag Wert; Sie können d.values() oder d.itervalues() verwenden, um die xs zu erhalten.

NB. hier gewinnt der letzte passende Gegenstand; Um den ersten zu gewinnen, iterieren Sie rückwärts.

+0

Sobald Sie auch Filter verwenden() (http://docs.python.org/2/library/functions. html # filter), die wegen der Inline-For-Schleife etwas schneller sein sollte. – pypat

+0

Danke. Dies funktioniert (Verwendung des Wörterbuchs), aber ist es der "beste" Weg, dies zu erreichen? Die von pypat vorgeschlagene Lösung scheint eher pythonisch zu sein. – v3gard

+1

@pypat: Ich nehme an, Sie könnten, mit dem Prädikat, dem Dict vorher ungesehene Werte hinzufügen, oder eigentlich nur eine Menge: 's = set()', dann 'filter (lambda x: False wenn x.tag in s else (s.add (x.tag) oder True), myList) '. Danke für den Vorschlag! Die 'für'-und-dict-basierte Version fühlt sich für mich jedoch einfacher an, daher würde ich vor dem Wechsel einen Benchmark erstellen. –

9

können Sie python dict comprehension

{x.tag: x for x in myList}.values() 

Für Ihr Beispiel verwenden:

>>> class MyClass(object): 
...  def __init__(self, classId, tag): 
...   self.classId = classId 
...   self.tag = tag 
... 
>>> myList = [MyClass(1, "ABC"), MyClass(2, "DEF"), MyClass(3, "DEF")] 
>>> uniqList = {x.tag: x for x in myList}.values() 
>>> print [x.classId for x in uniqList] 
[1, 3] 
Verwandte Themen