Исчерпывающее руководство по функции map в Python для обработки данных

Введение

Мы можем использовать встроенную функцию Python map() для применения функции к каждому элементу в итерируемом объекте (например, списке или словаре) и возвращать новый итератор для получения результатов. map() возвращает объект map (итератор), который мы можем использовать в других частях нашей программы. Мы также можем передать объект map в функцию list() или другой тип последовательности, чтобы создать итерируемый объект.

Синтаксис функции map() выглядит следующим образом:

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

Вместо использования for цикла функция map() предоставляет способ применения функции к каждому элементу в итерируемом объекте. Поэтому она часто может быть более производительной, так как применяет функцию к одному элементу за раз, а не создаёт копии элементов в другой итерируемый объект. Это особенно полезно при работе с программами, обрабатывающими большие наборы данных. map() также может принимать несколько итерируемых объектов в качестве аргументов для функции, отправляя по одному элементу из каждого итерируемого объекта в функцию за раз.

В этом уроке мы рассмотрим три различных способа работы с map(): с lambda функцией, с пользовательской функцией и, наконец, с встроенной функцией, использующей несколько итерабельных аргументов.

Использование функции Lambda

Первый аргумент для map() — это функция, которую мы используем для применения к каждому элементу. Python вызывает функцию один раз для каждого элемента в итерабельном объекте, который мы передаем в map(), и возвращает обработанный элемент в объекте map. Для первого аргумента функции мы можем либо передать пользовательскую функцию, либо воспользоваться lambda функциями, особенно когда выражение менее сложное.

Синтаксис map() с функцией lambda выглядит следующим образом:

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

С списком, подобным следующему, мы можем реализовать lambda функцию с выражением, которое мы хотим применить к каждому элементу нашего списка:

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

Чтобы применить выражение к каждому из наших чисел, мы можем использовать map() и lambda:

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

Здесь мы объявляем элемент в нашем списке как x. Затем мы добавляем наше выражение. Мы передаем наш список чисел как итерабельный объект для map().

Чтобы сразу получить результаты этого, мы выводим список объекта map:

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

Мы использовали list(), чтобы объект map возвращался нам в виде списка, а не в виде менее читаемого объекта, такого как: <map object at 0x7fc250003a58>. Объект map является итератором по нашим результатам, поэтому мы можем перебрать его с помощью for или использовать list(), чтобы превратить его в список. Мы делаем это здесь, потому что это хороший способ просмотреть результаты.

В конечном итоге map() наиболее полезна при работе с большими наборами данных, поэтому мы, вероятно, будем работать с объектом map дальше и, как правило, не будем использовать конструктор, такой как list(), на них.

Для меньших наборов данных списковые выражения могут быть более подходящими, но для целей этого учебника мы используем небольшой набор данных для демонстрации map().

Реализация функции, определенной пользователем

Аналогично lambda мы можем использовать функцию, которую мы определили, чтобы применить ее к итерируемому объекту. В то время как функции lambda более полезны для реализации, когда вы работаете с однострочным выражением, функции, определенные пользователем, более целесообразны, когда выражение усложняется. Кроме того, когда нам нужно передать другой фрагмент данных функции, которую вы применяете к вашему итерируемому объекту, функции, определенные пользователем, могут быть лучшим выбором для читабельности.

Например, в следующем итерируемом объекте каждый элемент представляет собой словарь, который содержит различные детали о каждом из наших аквариумных существ:

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

Мы решили, что все обитатели аквариума на самом деле переедут в один и тот же резервуар. Нам нужно обновить наши записи, чтобы отразить, что все наши существа переезжают в резервуар 42. Чтобы map() мог получить доступ к каждому словарю и каждой паре ключ:значение в словарях, мы создаем вложенную функцию:

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)

Мы определяем функцию assign_to_tank(), которая принимает aquarium_creatures и new_tank_number в качестве параметров. В assign_to_tank() мы передаем apply() как функцию для map() в последней строке. Функция assign_to_tank вернет итератор, полученный из map().

apply() принимает x в качестве аргумента, который представляет элемент в нашем списке — один словарь.

Далее мы определяем, что x является ключом "tank number" из aquarium_creatures и что он должен хранить переданный new_tank_number. Мы возвращаем каждый элемент после применения нового номера резервуара.

Мы вызываем assign_to_tank() с нашим списком словарей и новым номером резервуара, который мы хотим заменить для каждого существа:

assigned_tanks = assign_to_tank(aquarium_creatures, 42)

После завершения функции у нас есть объект карты, сохраненный в переменной assigned_tanks, который мы преобразуем в список и выводим:

print(list(assigned_tanks))

Мы получим следующий вывод от этой программы:

Output
[{'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'}]

Мы сопоставили новый номер резервуара с нашим списком словарей. Используя функцию, которую мы определяем, мы можем эффективно использовать map(), чтобы применить функцию к каждому элементу списка.

Использование встроенной функции с несколькими итерируемыми объектами

Так же, как и функции lambda или наши собственные определенные функции, мы можем использовать встроенные функции Python с map(). Чтобы применить функцию с несколькими итерируемыми объектами, мы передаем имя другого итерируемого объекта после первого. Например, используя функцию pow(), которая принимает два числа, чтобы найти степень базового числа к заданному показателю.

Здесь у нас есть списки целых чисел, которые мы хотели бы использовать с pow():

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

Затем мы передаем pow() как нашу функцию в map() и предоставляем два списка в качестве наших итерируемых объектов:

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

print(numbers_powers)

map() применит функцию pow() к одному и тому же элементу в каждом списке, чтобы предоставить степень. Поэтому наши результаты покажут 2**1, 4**2, 6**3 и так далее:

Output
[2, 16, 216, 4096, 100000]

Если мы предоставим map() итерируемый объект, который длиннее другого, map() прекратит вычисления, как только достигнет конца самого короткого итерируемого объекта. В следующей программе мы расширяем base_numbers тремя дополнительными числами:

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)

В результате ничего не изменится в расчетах этой программы, и она по-прежнему даст тот же результат:

Output
[2, 16, 216, 4096, 100000]

Мы использовали функцию map() с встроенной функцией Python и увидели, что она может обрабатывать несколько итерируемых объектов. Мы также рассмотрели, что map() будет продолжать обрабатывать несколько итерируемых объектов, пока не достигнет конца итерируемого объекта с наименьшим количеством элементов.

Заключение

В этом руководстве мы исследовали различные методы использования функции map() в Python. Теперь у вас есть возможность использовать map() с пользовательскими функциями, выражениями lambda и другими встроенными функциями. Кроме того, map() можно применять к функциям, которые требуют несколько итерируемых объектов, что повышает его универсальность в задачах обработки данных.

Для демонстрационных целей мы преобразовали результаты из map() непосредственно в список. В практических приложениях возвращаемый объект map можно дополнительно обрабатывать в соответствии с конкретными потребностями.

Чтобы углубить ваше понимание Python, пожалуйста, воспользуйтесь следующими ресурсами:

Эти ресурсы предоставят вам всестороннее понимание возможностей Python и того, как эффективно их использовать в ваших проектах.

Если вы хотите узнать больше о Python, ознакомьтесь с нашей серией Как программировать на Python и нашей страницей по теме Python. Чтобы узнать больше о работе с наборами данных в функциональном программировании, ознакомьтесь с нашей статьей о функции filter().

Часто задаваемые вопросы

Что делает map() в Python?

Функция map() в Python принимает функцию и один или несколько итерируемых объектов и возвращает итератор, который применяет данную функцию к каждому элементу предоставленных итерируемых объектов. Другими словами, она “отображает” функцию на каждый элемент в итерируемом объекте. Например:

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

Здесь squares будет итератором 1, 4, 9, 16.

Как создать map в Python?

Вы создаете объект map, вызывая встроенную функцию map() с функцией и как минимум одним итерируемым объектом в качестве аргументов. Например:

def add_one(x):
    return x + 1

my_list = [1, 2, 3]
mapped = map(add_one, my_list)  # Создает объект map

Затем вы можете итерировать по mapped или преобразовать его в список, чтобы увидеть результаты:

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

Является ли map ленивым в Python?

Да, в Python 3 map() возвращает ленивый итератор, что означает, что он не обрабатывает и не хранит все результаты в памяти сразу. Вместо этого он вычисляет каждый результат по мере необходимости, когда вы итерируете по нему. Это может быть более эффективным по памяти, особенно для больших наборов данных, но это также означает, что вы не можете напрямую индексировать или многократно итерировать по одному и тому же объекту map без его реконструкции.

Как работает функция map()?

Функция map() работает следующим образом:

  1. Вы предоставляете функцию и один или несколько итерируемых объектов.
  2. map() извлекает элемент из каждого итерируемого объекта.
  3. Она вызывает функцию с этими элементами в качестве аргументов.
  4. Она возвращает результат вызова этой функции.
  5. Этот процесс повторяется, пока один из итерируемых объектов не закончится.

Если задано несколько итерируемых объектов, map() останавливается, когдаShortest итерируемый объект исчерпан. Например:

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

Стоит ли использовать map в Python?

Стоит ли использовать map() зависит от личных предпочтений и читаемости:

Плюсы:

  • В некоторых случаях это может быть более лаконично.
  • Это может быть немного быстрее, чем списковые включения в определенных сценариях (хотя часто незначительно).

Минусы:

  • Код, использующий списковые включения или генераторные выражения, часто считается более «питоническим» и более читаемым.
  • Новые программисты на Python могут найти списковые включения более интуитивными.

Короче говоря, используйте map(), если это делает ваш код более ясным и прямым. В противном случае списковые включения или генераторные выражения являются очень распространенной альтернативой.

Как преобразовать map в строку в Python?

Объект map является итератором, а не строкой. Если вы хотите преобразовать результаты вызова map() в строку, вам сначала нужно пройти по нему. Распространенные подходы включают:

  • Преобразование в список, а затем в строковое представление:
mapped = map(str, [1, 2, 3])
string_representation = str(list(mapped))  # "[‘1’, ‘2’, ‘3’]"
  • Объединение результатов, если они являются строковыми элементами:
mapped = map(str, [1, 2, 3])
joined_string = ''.join(mapped)  # "123"

Лучший метод зависит от того, хотите ли вы получить человекочитаемое представление списка (str(list(...))) или конкатенацию результатов (''.join(...)).

Что делает map count()?

map объекты в Python не имеют встроенного метода count(). Метод count() доступен для списков, строк и некоторых других коллекций. Если вы хотите подсчитать количество вхождений значения, полученного с помощью объекта map, вам сначала нужно преобразовать его в список (что потребляет итератор):

mapped = map(lambda x: x*2, [1, 2, 3, 2])
mapped_list = list(mapped)
count_of_4 = mapped_list.count(4)  # 2, потому что 2*2=4 появляется дважды

Если вам нужно количество без преобразования в список, вы можете итеративно пройтись по элементам:

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

Что делают map и filter в Python?

  • map(function, iterable): Применяет функцию к каждому элементу итерируемого объекта и возвращает итератор результатов.

  • filter(function, iterable): Возвращает итератор элементов из итерируемого объекта, для которых функция(element) возвращает True. Если функция равна None, она возвращает элементы, которые являются истинными сами по себе.

Например:

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 преобразует каждый элемент, в то время как filter выбирает определенные элементы на основе условия.

Source:
https://www.digitalocean.com/community/tutorials/how-to-use-the-python-map-function