Załóżmy, że tworzę prostą klasę, która będzie działać podobnie do struktury w stylu C, aby po prostu przechowywać elementy danych. Próbuję dowiedzieć się, jak przeszukać listę obiektów dla obiektów z atrybutem równym określonej wartości. Poniżej znajduje się trywialny przykład ilustrujący, co próbuję zrobić.
Na przykład:
class Data:
pass
myList = []
for i in range(20):
data = Data()
data.n = i
data.n_squared = i * i
myList.append(data)
Jak mam przejść do przeszukiwania listy myList, aby określić, czy zawiera ona element z n == 5?
Szukałem w Google i przeszukiwałem dokumentację Pythona i myślę, że mógłbym to zrobić ze zrozumieniem listy, ale nie jestem pewien. Mógłbym dodać, że przy okazji muszę używać Pythona 2.4.3, więc żadne nowe funkcje gee-whiz 2.6 lub 3.x nie są dla mnie dostępne.
Odpowiedzi:
Możesz uzyskać listę wszystkich pasujących elementów ze zrozumieniem listy:
[x for x in myList if x.n == 30] # list of all elements with .n==30
Jeśli chcesz po prostu określić, czy lista zawiera dowolny element, który pasuje i zrobić to (względnie) wydajnie, możesz to zrobić
def contains(list, filter): for x in list: if filter(x): return True return False if contains(myList, lambda x: x.n == 3) # True if any element has .n==3 # do stuff
źródło
Prosty, elegancki i potężny:
Wyrażenie generatora w połączeniu z wbudowanym… (python 2.5+)
any(x for x in mylist if x.n == 10)
Używa
any()
wbudowanego języka Python , który jest zdefiniowany w następujący sposób:def any(iterable): for element in iterable: if element: return True return False
źródło
any(x for x in mylist if x['n'] == 10)
ale to dobry pomysłDla kompletności nie zapominajmy o najprostszej rzeczy, która mogłaby zadziałać:
for i in list: if i.n == 5: # do something with it print "YAY! Found one!"
źródło
[x for x in myList if x.n == 30] # list of all matches [x.n_squared for x in myList if x.n == 30] # property of matches any(x.n == 30 for x in myList) # if there is any matches [i for i,x in enumerate(myList) if x.n == 30] # indices of all matches def first(iterable, default=None): for item in iterable: return item return default first(x for x in myList if x.n == 30) # the first match, if any
źródło
filter(lambda x: x.n == 5, myList)
źródło
lambda
s.Możesz użyć
in
do wyszukania elementu w kolekcji i listy złożonej, aby wyodrębnić pole, które Cię interesuje. To (działa dla list, zbiorów, krotek i wszystkiego, co definiuje__contains__
lub__getitem__
).if 5 in [data.n for data in myList]: print "Found it"
Zobacz też:
źródło
Powinieneś dodać a
__eq__
i__hash__
metodę do swojejData
klasy, może ona sprawdzić, czy__dict__
atrybuty są równe (te same właściwości), a następnie, czy ich wartości są równe.Jeśli to zrobiłeś, możesz użyć
test = Data() test.n = 5 found = test in myList
Słowo
in
kluczowe sprawdza, czytest
jest wmyList
.Jeśli chcesz mieć tylko
n
nieruchomość w domu,Data
możesz użyć:class Data(object): __slots__ = ['n'] def __init__(self, n): self.n = n def __eq__(self, other): if not isinstance(other, Data): return False if self.n != other.n: return False return True def __hash__(self): return self.n myList = [ Data(1), Data(2), Data(3) ] Data(2) in myList #==> True Data(5) in myList #==> False
źródło
Rozważ użycie słownika:
myDict = {} for i in range(20): myDict[i] = i * i print(5 in myDict)
źródło
Innym sposobem, w jaki możesz to zrobić, jest użycie funkcji next ().
matched_obj = next(x for x in list if x.n == 10)
źródło