Jak używać funkcji filtrowania w Pythonie
Wprowadzenie
Wbudowana w Pythonie funkcja filter()
może być użyta do utworzenia nowego iteratora z istniejącej iterowalnej (takiej jak lista lub słownik), która będzie efektywnie odfiltrowywać elementy przy użyciu podanej przez nas funkcji. Iterowalna jest obiektem Pythona, który może być „iterowany po”, to znaczy, że zwróci elementy w sekwencji takiej, że możemy użyć go w pętli for
.
Podstawowa składnia funkcji filter()
to:
filter(function, iterable)
Zwróci ona obiekt filtru, który jest iterowalną. Możemy użyć funkcji takiej jak list()
, aby utworzyć listę wszystkich elementów zwróconych w obiekcie filtru.
Funkcja filter()
zapewnia sposób filtrowania wartości, który często może być bardziej wydajny niż zrozumienie listy, zwłaszcza gdy zaczynamy pracować z większymi zestawami danych. Na przykład, list comprehension utworzy nową listę, co zwiększy czas działania dla tego przetwarzania. Oznacza to, że po tym jak nasze list comprehension zakończy swoje wyrażenie, będziemy mieli dwie listy w pamięci. Natomiast filter()
utworzy prosty obiekt, który będzie zawierał referencję do oryginalnej listy, przekazaną funkcję oraz indeks miejsca na oryginalnej liście, co zajmie mniej pamięci.
W tym poradniku omówimy cztery różne sposoby użycia filter()
: z dwiema różnymi strukturami iterowalnymi, z funkcją lambda
i bez zdefiniowanej funkcji.
Usługiwanie filter() z funkcją
Pierwszym argumentem filter()
jest funkcja, której używamy do decydowania, czy uwzględniać czy odfiltrować każdy element. Funkcja jest wywoływana raz dla każdego elementu w iterable przekazanej jako drugi argument i za każdym razem, gdy zwraca False
, wartość jest odrzucana. Ponieważ ten argument jest funkcją, możemy albo przekazać normalną funkcję, albo skorzystać z funkcji lambda
, szczególnie gdy wyrażenie jest mniej złożone.
Poniżej przedstawiona jest składnia funkcji lambda
z filter()
:
filter(lambda item: item expression, iterable)
W przypadku listy, jak poniżej, możemy zawrzeć funkcję lambda
z wyrażeniem, względem którego chcemy ocenić każdy element z listy:
creature_names =
Aby przefiltrować tę listę w celu znalezienia nazw naszych stworzeń akwariowych, które zaczynają się od samogłoski, możemy uruchomić następującą funkcję lambda
:
print(list(filter(lambda x: x.lower() in 'aeiou', creature_names)))
Tutaj deklarujemy element naszej listy jako x
. Następnie ustawiamy nasze wyrażenie, aby uzyskać dostęp do pierwszego znaku każdego łańcucha (lub znaku „zero”), więc x
. Zmniejszanie wielkości liter w każdej z nazw zapewnia, że będzie to dopasowanie liter do ciągu w naszym wyrażeniu, 'aeiou'
.
Na koniec przekazujemy iterowalną creature_names
. Podobnie jak w poprzedniej sekcji stosujemy list()
do wyniku, aby utworzyć listę z iteratora filter()
zwraca.
Wynik będzie następujący:
Output
Ten sam wynik można osiągnąć za pomocą funkcji, którą zdefiniujemy:
creature_names = def names_vowels(x): return x.lower() in 'aeiou'filtered_names = filter(names_vowels, creature_names)print(list(filtered_names))
Nasza funkcja names_vowels
definiuje wyrażenie, które zaimplementujemy do filtrowania creature_names
.
Ponownie, dane wyjściowe wyglądałyby następująco:
Output
Ogółem, za pomocą funkcji lambda
osiągniemy taki sam rezultat jak wtedy, gdy użyjemy funkcji regularnej. Konieczność definiowania funkcji regularnej rośnie wraz ze wzrostem złożoności wyrażeń filtrujących nasze dane, co prawdopodobnie przyczyni się do zwiększenia czytelności naszego kodu.
Używanie None z filter()
Możemy przekazać None
jako pierwszy argument do filter()
, aby zwrócony iterator odfiltrował każdą wartość, którą Python uważa za „fałszywą”. Ogólnie rzecz biorąc, Python uważa wszystko o długości 0
(takie jak pusta lista lub pusty ciąg znaków) lub numerycznie równoważne 0
za fałszywe, stąd użycie terminu „falsy”.”
W poniższym przypadku chcemy przefiltrować naszą listę, aby pokazać tylko numery zbiorników w naszym akwarium:
aquarium_tanks = , {}]
W tym kodzie mamy listę zawierającą liczby całkowite, puste ciągi i wartość boolean.
filtered_tanks = filter(None, aquarium_tanks)
Używamy funkcji filter()
z None
i przekazujemy listę aquarium_tanks
jako naszą iterowalną. Ponieważ przekazaliśmy None
jako pierwszy argument, sprawdzimy, czy elementy na naszej liście są uważane za fałszywe.
print(list(filtered_tanks))
Następnie zawijamy filtered_tanks
w funkcję list()
tak, aby zwracała ona listę dla filtered_tanks
podczas drukowania.
Tutaj na wyjściu widać tylko liczby całkowite. Wszystkie elementy, które zostały ocenione na False
, które są równoważne 0
pod względem długości, zostały usunięte przez filter()
:
Output
Uwaga: Gdybyśmy nie użyli list()
i wydrukowali filtered_tanks
otrzymalibyśmy obiekt filtra coś takiego: <filter object at 0x7fafd5903240>
. Obiekt filtra jest iterowalny, więc możemy go zapętlić za pomocą for
lub użyć list()
aby zamienić go w listę, co tutaj zrobimy, ponieważ jest to dobry sposób na przeglądanie wyników.
Z None
wykorzystaliśmy filter()
do szybkiego usunięcia z naszej listy pozycji, które zostały uznane za fałszywe.
Usługiwanie filter() z listą słowników
Gdy mamy bardziej złożoną strukturę danych, wciąż możemy użyć filter()
do oceny każdego z elementów. Na przykład, jeśli mamy listę słowników, nie tylko chcemy iterować nad każdym elementem na liście – jednym ze słowników – ale możemy również chcieć iterować nad każdą parą klucz:wartość w słowniku, aby ocenić wszystkie dane.
Przykładowo, powiedzmy, że mamy listę wszystkich stworzeń w naszym akwarium wraz z różnymi szczegółami na temat każdego z nich:
aquarium_creatures =
Chcemy przefiltrować te dane według ciągu wyszukiwania, który podajemy do funkcji. Aby filter()
mieć dostęp do każdego słownika i każdego elementu w słownikach, konstruujemy funkcję zagnieżdżoną, jak poniżej:
def filter_set(aquarium_creatures, search_string): def iterator_func(x): for v in x.values(): if search_string in v: return True return False return filter(iterator_func, aquarium_creatures)
Zdefiniujemy funkcję filter_set()
, która przyjmuje aquarium_creatures
i search_string
jako parametry. W filter_set()
przekazujemy nasz iterator_func()
jako funkcję do filter()
. Funkcja filter_set()
zwróci iterator wynikający z filter()
.
iterator_func()
przyjmuje jako argument x
, który reprezentuje element naszej listy (czyli pojedynczy słownik).
Następnie pętla for
uzyskuje dostęp do wartości w każdej parze klucz:wartość w naszych słownikach, a następnie używa instrukcji warunkowej, aby sprawdzić, czy search_string
znajduje się w v
, reprezentującym wartość.
Tak jak w naszych poprzednich przykładach, jeśli wyrażenie ewaluuje do True
funkcja dodaje element do obiektu filtra. Zostanie ona zwrócona po zakończeniu działania funkcji filter_set()
. Umieszczamy return False
poza naszą pętlą, tak aby sprawdzała ona każdy element w każdym słowniku, zamiast wracać po sprawdzeniu tylko pierwszego słownika.
Wywołujemy filter_set()
z naszą listą słowników i wyszukiwanym hasłem, dla którego chcemy znaleźć dopasowania:
filtered_records = filter_set(aquarium_creatures, "2")
Po zakończeniu działania funkcji mamy nasz obiekt filtra zapisany w zmiennej filtered_records
, którą zamieniamy na listę i drukujemy:
print(list(filtered_records))
Z tego programu otrzymamy następujące dane wyjściowe:
Output
Przefiltrowaliśmy listę słowników za pomocą wyszukiwanego ciągu 2
. Widzimy, że zwrócone zostały trzy słowniki, które zawierały numer zbiornika z 2
. Użycie naszej własnej zagnieżdżonej funkcji pozwoliło nam uzyskać dostęp do każdego elementu i efektywnie sprawdzić każdy z nich względem wyszukiwanego ciągu znaków.
Podsumowanie
W tym poradniku poznaliśmy różne sposoby użycia funkcji filter()
w Pythonie. Teraz możesz używać filter()
z własną funkcją, funkcją lambda
lub z None
do filtrowania elementów w różnie złożonych strukturach danych.
Pomimo że w tym tutorialu wydrukowaliśmy wyniki z filter()
od razu w formacie listy, jest prawdopodobne, że w naszych programach użylibyśmy zwróconego obiektu filter()
i dalej manipulowali danymi.
Jeśli chcesz nauczyć się więcej Pythona, sprawdź naszą serię How To Code in Python 3 i naszą stronę tematyczną Pythona.