Wyszukiwanie w witrynie

Kompletny przewodnik po funkcjach mapowania w języku Python do przetwarzania danych


Wstęp

Możemy użyć wbudowanej funkcji Pythona map(), aby zastosować funkcję do każdego elementu w iterowalnym elemencie (takim jak lista lub słownik) i zwrócić nowy iterator w celu pobrania wyników. map() zwraca obiekt mapy (iterator), którego możemy użyć w innych częściach naszego programu. Możemy także przekazać obiekt mapy do funkcji list() lub innego typu sekwencji, aby utworzyć iterację.

Składnia funkcji map() jest następująca:

map(function, iterable, [iterable 2, iterable 3, ...])

Zamiast używać pętli for, funkcja map() umożliwia zastosowanie funkcji do każdego elementu w iteracji. Dlatego często może być bardziej wydajny, ponieważ stosuje funkcję tylko do jednego elementu na raz, zamiast tworzyć kopie elementów do innego, który można iterować. Jest to szczególnie przydatne podczas pracy z programami przetwarzającymi duże zbiory danych. Funkcja map() może także przyjmować wiele iteracji jako argumenty funkcji, wysyłając jednocześnie do funkcji po jednym elemencie z każdej iteracji.

W tym samouczku omówimy trzy różne sposoby pracy z funkcją map(): z funkcją lambda, z funkcją zdefiniowaną przez użytkownika i na koniec z wbudowaną funkcją w funkcji przy użyciu wielu iterowalnych argumentów.

Korzystanie z funkcji Lambda

Pierwszym argumentem map() jest funkcja, której używamy do zastosowania do każdego elementu. Python wywołuje tę funkcję raz dla każdego elementu iteracyjnego, który przekazujemy do map() i zwraca manipulowany element w obiekcie mapy. Jako pierwszy argument funkcji możemy przekazać funkcję zdefiniowaną przez użytkownika lub skorzystać z funkcji lambda, szczególnie gdy wyrażenie jest mniej złożone.

Składnia map() z funkcją lambda jest następująca:

map(lambda item: item[] expression, iterable)

Za pomocą listy podobnej do poniższej możemy zaimplementować funkcję lambda z wyrażeniem, które chcemy zastosować do każdego elementu na naszej liście:

numbers = [10, 15, 21, 33, 42, 55]

Aby zastosować wyrażenie do każdej z naszych liczb, możemy użyć map() i lambda:

mapped_numbers = list(map(lambda x: x * 2 + 3, numbers))

Tutaj deklarujemy element na naszej liście jako x. Następnie dodajemy nasze wyrażenie. Naszą listę liczb przekazujemy jako iterowalną dla funkcji map().

Aby natychmiast otrzymać wyniki, wypisujemy listę obiektu map:

print(mapped_numbers)
[23, 33, 45, 69, 87, 113]

Użyliśmy list(), dzięki czemu obiekt mapy jest nam zwracany w postaci listy, a nie obiektu mniej czytelnego dla człowieka, takiego jak: . Obiekt mapy jest iteratorem naszych wyników, więc możemy nad nim zapętlić funkcję for lub możemy użyć metody list(), aby zamienić go w listę. Robimy to tutaj, ponieważ jest to dobry sposób na sprawdzenie wyników.

Ostatecznie funkcja map() jest najbardziej użyteczna podczas pracy z dużymi zbiorami danych, więc prawdopodobnie będziemy dalej pracować z obiektem mapy i generalnie nie będziemy używać konstruktora takiego jak list() na nich.

W przypadku mniejszych zestawów danych bardziej odpowiednie mogą być wyrażenia listowe, ale na potrzeby tego samouczka użyjemy małego zestawu danych do zademonstrowania funkcji map().

Implementacja funkcji zdefiniowanej przez użytkownika

Podobnie jak w przypadku lambda, możemy użyć funkcji, którą zdefiniowaliśmy w celu zastosowania do obiektu iterowalnego. Podczas gdy funkcje lambda są bardziej przydatne do implementacji, gdy pracujesz z wyrażeniem jednowierszowym, funkcje zdefiniowane przez użytkownika są bardziej odpowiednie, gdy wyrażenie staje się bardziej złożone. Co więcej, gdy musimy przekazać kolejną porcję danych do funkcji, którą stosujesz do iterowalnych funkcji, funkcje zdefiniowane przez użytkownika mogą być lepszym wyborem ze względu na czytelność.

Na przykład w poniższej iteracji każdy element jest słownikiem zawierającym różne szczegóły na temat każdego z naszych stworzeń akwariowych:

aquarium_creatures = [
 {"name": "sammy", "species": "shark", "tank number": 11, "type": "fish"},
 {"name": "ashley", "species": "crab", "tank number": 25, "type": "shellfish"},
 {"name": "jo", "species": "guppy", "tank number": 18, "type": "fish"},
 {"name": "jackie", "species": "lobster", "tank number": 21, "type": "shellfish"},
 {"name": "charlie", "species": "clownfish", "tank number": 12, "type": "fish"},
 {"name": "olly", "species": "green turtle", "tank number": 34, "type": "turtle"}
]

Zdecydowaliśmy, że tak naprawdę wszystkie stworzenia akwariowe przeniosą się do tego samego zbiornika. Musimy zaktualizować nasze dane, aby uwzględnić fakt, że wszystkie nasze stworzenia przenoszą się do zbiornika 42. Aby funkcja map() miała dostęp do każdego słownika i każdej pary klucz:wartość w słownikach, konstruujemy funkcję zagnieżdżoną:

def assign_to_tank(aquarium_creatures, new_tank_number):
 def apply(x):
  x["tank number"] = new_tank_number
  return x
 return map(apply, aquarium_creatures)

Definiujemy funkcję przypisz_to_tank(), która przyjmuje parametry aquarium_creatures i new_tank_number. W sign_to_tank() przekazujemy apply() jako funkcję do map() w ostatniej linii. Funkcja przypisz_to_tank zwróci iterator będący wynikiem funkcji map().

apply() przyjmuje x jako argument, który reprezentuje element na naszej liście — pojedynczy słownik.

Następnie definiujemy, że x jest kluczem „numer zbiornika” z aquarium_creatures i że powinien przechowywać przekazany klucz w new_tank_number. Każdy towar zwracamy po zastosowaniu nowego numeru zbiornika.

Wywołujemy funkcję przypisania_to_tank() z naszą listą słowników i nowym numerem czołgu, który chcemy zastąpić dla każdego stworzenia:

assigned_tanks = assign_to_tank(aquarium_creatures, 42)

Po zakończeniu funkcji obiekt naszej mapy jest przechowywany w zmiennej przypisany_tanks, którą zamieniamy na listę i drukujemy:

print(list(assigned_tanks))

Otrzymamy następujące dane wyjściowe z tego programu:

[{'name': 'sammy', 'species': 'shark', 'tank number': 42, 'type': 'fish'}, {'name': 'ashley', 'species': 'crab', 'tank number': 42, 'type': 'shellfish'}, {'name': 'jo', 'species': 'guppy', 'tank number': 42, 'type': 'fish'}, {'name': 'jackie', 'species': 'lobster', 'tank number': 42, 'type': 'shellfish'}, {'name': 'charlie', 'species': 'clownfish', 'tank number': 42, 'type': 'fish'}, {'name': 'olly', 'species': 'green turtle', 'tank number': 42, 'type': 'turtle'}]

Dodaliśmy nowy numer czołgu do naszej listy słowników. Używając zdefiniowanej przez nas funkcji, możemy włączyć funkcję map(), aby efektywnie zastosować tę funkcję do każdego elementu listy.

Używanie funkcji wbudowanej z wieloma obiektami iteracyjnymi

W ten sam sposób, co funkcje lambda lub nasze własne zdefiniowane funkcje, możemy używać wbudowanych funkcji Pythona za pomocą map(). Aby zastosować funkcję z wieloma iterowalnymi nazwami, po pierwszej przekazujemy kolejną iterowalną nazwę. Na przykład użycie funkcji pow(), która pobiera dwie liczby w celu obliczenia potęgi liczby podstawowej do podanego wykładnika.

Tutaj mamy listę liczb całkowitych, których chcielibyśmy użyć w funkcji pow():

base_numbers = [2, 4, 6, 8, 10]
powers = [1, 2, 3, 4, 5]

Następnie przekazujemy pow() jako naszą funkcję do map() i udostępniamy obie listy jako nasze iteracje:

numbers_powers = list(map(pow, base_numbers, powers))

print(numbers_powers)

map() zastosuje funkcję pow() do tego samego elementu na każdej liście, aby zapewnić moc. Dlatego nasze wyniki pokażą 2**1, 4**2, 6**3 i tak dalej:

[2, 16, 216, 4096, 100000]

Gdybyśmy udostępnili map() iterację, która byłaby dłuższa od drugiej, map() przestałaby obliczać, gdy dotrze do końca najkrótszej iteracji. W poniższym programie rozszerzamy base_numbers o trzy dodatkowe liczby:

base_numbers = [2, 4, 6, 8, 10, 12, 14, 16]
powers = [1, 2, 3, 4, 5]

numbers_powers = list(map(pow, base_numbers, powers))

print(numbers_powers)

W rezultacie nic nie zmieni się w obliczeniach tego programu, a zatem nadal będzie dawać ten sam wynik:

[2, 16, 216, 4096, 100000]

Użyliśmy funkcji map() z wbudowaną funkcją Pythona i przekonaliśmy się, że może ona obsługiwać wiele iteracji. Sprawdziliśmy również, że map() będzie kontynuować przetwarzanie wielu iteracji, aż dotrze do końca iteracji z najmniejszą liczbą elementów.

Wniosek

W tym samouczku omówiliśmy różne metody wykorzystania funkcji map() w Pythonie. Masz teraz możliwość używania funkcji map() z funkcjami niestandardowymi, wyrażeniami lambda i innymi funkcjami wbudowanymi. Dodatkowo funkcję map() można zastosować do funkcji wymagających wielu iteracji, co zwiększa jej wszechstronność w zadaniach przetwarzania danych.

W celach demonstracyjnych przekonwertowaliśmy wyniki funkcji map() bezpośrednio na listę. W praktycznych zastosowaniach zwrócony obiekt mapy można dalej manipulować, aby dostosować go do konkretnych potrzeb.

Aby pogłębić swoją wiedzę na temat języka Python, skorzystaj z następujących zasobów:

  • Samouczek dotyczący funkcji map() w języku Python zawierający bardziej szczegółowe przykłady i przypadki użycia.
  • Zrozumienie słowników w języku Python w celu poszerzenia wiedzy na temat struktur danych w języku Python.
  • Funkcje łańcuchowe w języku Python umożliwiające eksplorację różnych technik manipulacji ciągami.

Zasoby te pozwolą Ci kompleksowo zrozumieć możliwości Pythona i dowiedzieć się, jak skutecznie je wykorzystać w swoich projektach.

Jeśli chcesz dowiedzieć się więcej o języku Python, zapoznaj się z naszą serią Jak kodować w języku Python i naszą stroną tematyczną dotyczącą języka Python. Aby dowiedzieć się więcej o pracy ze zbiorami danych w programowaniu funkcjonalnym, przeczytaj nasz artykuł na temat funkcji filter().

Często zadawane pytania

Co robi map() w Pythonie?

Funkcja map() w Pythonie przyjmuje funkcję oraz jeden lub więcej obiektów iteracyjnych i zwraca iterator, który stosuje daną funkcję do każdego elementu dostarczonych obiektów iteracyjnych. Innymi słowy, „odwzorowuje” funkcję na każdy element iterowalnego obiektu. Na przykład:

numbers = [1, 2, 3, 4]
squares = map(lambda x: x**2, numbers)

Tutaj kwadraty będą iteratorem 1, 4, 9, 16.

Jak utworzyć mapę w Pythonie?

Tworzysz obiekt mapy, wywołując wbudowaną funkcję map() z funkcją i co najmniej jednym iterowalnym argumentem. Na przykład:

def add_one(x):
    return x + 1

my_list = [1, 2, 3]
mapped = map(add_one, my_list)  # Creates a map object

Następnie możesz iterować po mapowaniu lub konwertować go na listę, aby zobaczyć wyniki:

print(list(mapped))  # [2, 3, 4]

Czy mapa jest leniwa w Pythonie?

Tak, w Pythonie 3 funkcja map() zwraca leniwy iterator, co oznacza, że nie przetwarza ani nie przechowuje wszystkich wyników w pamięci na raz. Zamiast tego oblicza każdy wynik na żądanie podczas iteracji po nim. Może to oszczędzać pamięć, zwłaszcza w przypadku dużych zbiorów danych, ale oznacza również, że nie można bezpośrednio indeksować ani wielokrotnie iterować po tym samym obiekcie mapy bez jego rekonstrukcji.

Jak działa funkcja map()?

Funkcja map() działa w następujący sposób:

  1. Podajesz funkcję i jedną lub więcej iteracji.
  2. map() pobiera element z każdej iteracji.
  3. Wywołuje funkcję z tymi elementami jako argumentami.
  4. Daje wynik wywołania tej funkcji.
  5. Powtarza ten proces, aż do wyczerpania się którejkolwiek z iteracji.

Jeśli podano wiele obiektów iteracyjnych, map() zatrzymuje się, gdy wyczerpany zostanie najkrótszy możliwy do iteracji. Na przykład:

numbers = [1, 2, 3]
others = [10, 20, 30]
result = map(lambda x, y: x + y, numbers, others)
print(list(result))  # [11, 22, 33]

Czy powinienem używać map w Pythonie?

To, czy powinieneś używać map(), zależy od osobistych preferencji i czytelności:

Zalety:

  • W niektórych przypadkach może być bardziej zwięzły.
  • W niektórych scenariuszach może być nieco szybszy niż wyrażenia listowe (choć często nie znacząco).

Wady:

  • Kod wykorzystujący wyrażenia listowe lub wyrażenia generatorowe jest często uważany za bardziej „pythoniczny” i łatwiejszy do odczytania.
  • Nowsi programiści Pythona mogą uznać, że rozumienie list jest bardziej intuicyjne.

Krótko mówiąc, użyj map(), jeśli dzięki temu Twój kod będzie jaśniejszy i bardziej bezpośredni. W przeciwnym razie bardzo powszechną alternatywą są wyrażenia listowe lub wyrażenia generatorowe.

Jak przekonwertować mapę na ciąg znaków w Pythonie?

Obiekt map jest iteratorem, a nie ciągiem znaków. Jeśli chcesz przekonwertować wyniki wywołania map() na ciąg znaków, musisz najpierw wykonać po nim iterację. Typowe podejścia obejmują:

  • Konwersja na listę, a następnie na reprezentację w postaci ciągu znaków:
mapped = map(str, [1, 2, 3])
string_representation = str(list(mapped))  # "[‘1’, ‘2’, ‘3’]"
  • Łączenie wyników, jeśli są elementami łańcuchowymi:
mapped = map(str, [1, 2, 3])
joined_string = ''.join(mapped)  # "123"

Najlepsza metoda zależy od tego, czy chcesz mieć reprezentację listy czytelną dla człowieka (str(list(...))), czy konkatenację wyników (''.join(... )).

Co robi map count()?

Obiekty map w Pythonie nie mają wbudowanej metody count(). Metoda count() jest dostępna w przypadku list, ciągów znaków i niektórych innych kolekcji. Jeśli chcesz policzyć wystąpienia wartości generowanej przez obiekt mapy, musisz najpierw przekonwertować ją na listę (która zużywa iterator):

mapped = map(lambda x: x*2, [1, 2, 3, 2])
mapped_list = list(mapped)
count_of_4 = mapped_list.count(4)  # 2, because 2*2=4 appears twice

Jeśli potrzebujesz liczby bez konwertowania na listę, możesz wykonać iterację ręcznie:

count_of_value = sum(1 for x in map(lambda x: x*2, [1, 2, 3, 2]) if x == 4)

Co robią map i filter w Pythonie?

  • map(function, iterable): Stosuje funkcję do każdego elementu iterowalnego i zwraca iterator wyników.

  • filter(funkcja, iterowalna): Zwraca iterator elementów z iterowalnego, dla których funkcja(element) ma wartość True. Jeśli funkcja ma wartość None, zwraca elementy, które same w sobie są prawdziwe.

Na przykład:

nums = [1, 2, 3, 4, 5]
mapped_nums = map(lambda x: x*2, nums)        # [2, 4, 6, 8, 10]
filtered_nums = filter(lambda x: x > 2, nums) # [3, 4, 5]

map przekształca każdy element, podczas gdy filter wybiera określone elementy na podstawie warunku.

Powiązane artykuły: