Jestem programistą C, który tworzy coś w Pythonie. Wiem, jak wykonać następujące czynności w C (a zatem w logice podobnej do C zastosowanej w Pythonie), ale zastanawiam się, jaki jest sposób robienia tego w „Pythonie”.
Mam słownik d i chciałbym operować na podzbiorze elementów, tylko te, dla których klucz (ciąg) zawiera określony podciąg.
czyli logika C wyglądałaby następująco:
for key in d:
if filter_string in key:
# do something
else
# do nothing, continue
Wyobrażam sobie, że wersja Pythona byłaby podobna
filtered_dict = crazy_python_syntax(d, substring)
for key,value in filtered_dict.iteritems():
# do something
Znalazłem tutaj wiele postów dotyczących filtrowania słowników, ale nie mogłem znaleźć takiego, który dotyczyłby dokładnie tego.
Mój słownik nie jest zagnieżdżony i używam Pythona 2.7
python
python-2.7
dictionary
filtering
notatka
źródło
źródło
Odpowiedzi:
A co ze zrozumieniem dyktowania :
filtered_dict = {k:v for k,v in d.iteritems() if filter_string in k}
Jeśli to zobaczysz, powinno to być oczywiste, ponieważ całkiem dobrze brzmi jak angielski.
Ta składnia wymaga Pythona 2.7 lub nowszego.
W Pythonie 3 jest tylko
dict.items()
, nieiteritems()
więc używałbyś:filtered_dict = {k:v for (k,v) in d.items() if filter_string in k}
źródło
filtered_dict = {k:d[k] for k in d if filter_string in k}
?d[k]
wyszukiwania.# do something
w komentarzach, ale tutaj upuszczamy kilka kluczy.iteritems
w Pythonie 3? Nie sądzę. Więc moja wersja byłaby kompatybilna, nie?iteritems
zitems
, która jest taka sama jak w Pythonie 2.7-tychiteritems
.Wybierz wszystko, co jest najbardziej czytelne i łatwe w utrzymaniu. To, że możesz to zapisać w jednej linii, nie oznacza, że powinieneś. Twoje istniejące rozwiązanie jest bliskie temu, czego użyłbym inaczej niż użyłbym iteritemów, aby pominąć wyszukiwanie wartości, i nienawidzę zagnieżdżonych ifs, jeśli mogę ich uniknąć:
for key, val in d.iteritems(): if filter_string not in key: continue # do something
Jednak jeśli naprawdę chcesz, aby coś pozwoliło ci iterować przez filtrowany dykt, nie wykonałbym dwuetapowego procesu budowania przefiltrowanego dyktu, a następnie iterowania przez niego, ale zamiast tego użyj generatora, ponieważ co jest bardziej pythonowe (i niesamowite) niż generator?
Najpierw tworzymy nasz generator, a dobry projekt wymaga, aby był na tyle abstrakcyjny, aby można go było ponownie użyć:
# The implementation of my generator may look vaguely familiar, no? def filter_dict(d, filter_string): for key, val in d.iteritems(): if filter_string not in key: continue yield key, val
A potem możemy użyć generatora, aby rozwiązać twój problem ładnie i czysto za pomocą prostego, zrozumiałego kodu:
for key, val in filter_dict(d, some_string): # do something
Krótko mówiąc: generatory są niesamowite.
źródło
Możesz użyć wbudowanej funkcji filtru do filtrowania słowników, list itp. Na podstawie określonych warunków.
filtered_dict = dict(filter(lambda item: filter_str in item[0], d.items()))
Zaletą jest to, że można go używać do różnych struktur danych.
źródło
items:
powinno to byćitem:
w definicji lambda.input = {"A":"a", "B":"b", "C":"c"} output = {k:v for (k,v) in input.items() if key_satifies_condition(k)}
źródło
iteritems()
będzie bardziej wydajna niżitems()
.items()
, który działa jak Python 2.7iteritems
.Jonathon podał ci podejście, używając w swojej odpowiedzi dyktowania ze zrozumieniem . Oto podejście, które dotyczy części robienia czegoś .
Jeśli chcesz coś zrobić z wartościami słownika, nie potrzebujesz w ogóle rozumienia ze słownika:
Używam
iteritems(
), ponieważ oznaczyłeś swoje pytanie tagiempython-2.7results = map(some_function, [(k,v) for k,v in a_dict.iteritems() if 'foo' in k])
Teraz wynik będzie na liście z
some_function
zastosowaną do każdej pary klucz / wartość w słowniku, która mafoo
w swoim kluczu.Jeśli chcesz tylko zająć się wartościami i zignorować klucze, po prostu zmień rozumienie listy:
results = map(some_function, [v for k,v in a_dict.iteritems() if 'foo' in k])
some_function
może być wywoływalne, więc lambda również będzie działać:results = map(lambda x: x*2, [v for k,v in a_dict.iteritems() if 'foo' in k])
Lista wewnętrzna w rzeczywistości nie jest wymagana, ponieważ można również przekazać wyrażenie generatora do mapowania:
>>> map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2)) [4]
źródło
map(lambda a: a[0]*a[1], ((k,v) for k,v in {2:2, 3:2}.iteritems() if k == 2))
- to ci da[4]
.map
jest rozumienie listy.[f(v) for k, v in d.iteritems() if substring in k]
Myślę, że jest dużo bardziej czytelny i wydajniejszy.results = list(starmap(...))
Lubfor result in starmap(...): ...
).