2013-06-03 22 views
7

Mam listę wystąpień z tej samej klasy i chcę, aby moja lista różniła się w zależności od właściwości w klasie. Jaki jest najbardziej pytonowy sposób osiągnięcia tego?Jak utworzyć listę w Pythonie odrębną na podstawie właściwości klasy na liście?

Oto przykładowy kod:

#!/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) 

Jeśli chcę uporządkować moją listę obecnie na podstawie jednej z właściwości w MojaKlasa, zwykle po prostu posortować je według klucza, i ustawić klucz za pomocą wyrażenia lambda - tak:

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

$ python ./test.py 
1 
2 
3 

Czy jest możliwe aby użyć podobnej metody (lambda, mapę lub podobne), aby lista wyraźny opiera się na „tag” nieruchomości? Ponadto, jeśli jest to możliwe, jest to najbardziej "pythonic" sposób, aby lista różni się w oparciu o właściwość klasy na tej liście?

Próbowałem już szukają zarówno SO i Google tematów na ten temat, ale wszystkie wyniki znalazłem czynienia z prostych list, że tylko zawartych wartość liczbową, a nie niestandardowego obiektu ..

Odpowiedz

6

Zakładając właściwości, chce wprowadzić na to niezmienne, można użyć dict:

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

teraz d będzie zawierać pojedynczy x za tag wartości; możesz użyć d.values() lub d.itervalues(), aby uzyskać numer xs.

NB. tutaj ostatni pasujący element wygrywa; aby wygrać pierwszy, wykonaj iterację odwrotnie.

+0

Raz też użyć filtra() (http://docs.python.org/2/library/functions. html # filter), który powinien być nieco szybszy ze względu na wbudowaną pętlę for. – pypat

+0

Dziękuję. To (użycie słownika) działa, ale czy jest to "najlepszy" sposób, aby to osiągnąć? Rozwiązanie sugerowane przez Pypat wydaje się bardziej pythonic. – v3gard

+1

@pypat: Sądzę, że mógłbyś, używając predykatu dodającego wcześniej-niewidziane wartości do dyktafonu, lub właściwie tylko zestawu: 's = set()', następnie 'filter (lambda x: False if x.tag in s else (s.add (x.tag) lub True), myList) '. Dzieki za sugestie! Wersja "na" i na "dyktando" wydaje mi się jednak łatwiejsza, więc sprawdziłbym ją przed zmianą. –

9

Można użyć python dict comprehension

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

Dla przykładu:

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