Как работают функции map(), filter() и reduce()?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Как работают функции map(), filter() и reduce()?
Общая идея: Функциональное программирование
map(), filter() и reduce() — это основные функции функционального программирования в Python. Они позволяют обрабатывать последовательности данных без явных циклов, применяя функцию к каждому элементу.
Это функции высшего порядка (higher-order functions) — они принимают другие функции как аргументы.
map() — Преобразование каждого элемента
map() применяет функцию к каждому элементу итерируемого объекта и возвращает итератор результатов.
# Синтаксис: map(function, iterable)
def square(x):
return x ** 2
numbers = [1, 2, 3, 4, 5]
result = map(square, numbers)
print(list(result)) # [1, 4, 9, 16, 25]
# С лямбда-функцией
result = map(lambda x: x ** 2, numbers)
print(list(result)) # [1, 4, 9, 16, 25]
# Несколько итерируемых объектов
nums1 = [1, 2, 3]
nums2 = [10, 20, 30]
result = map(lambda x, y: x + y, nums1, nums2)
print(list(result)) # [11, 22, 33]
Как это работает внутри:
def my_map(func, iterable):
"""Упрощённая реализация map()"""
for item in iterable:
yield func(item) # Ленивое вычисление!
numbers = [1, 2, 3]
result = my_map(lambda x: x * 2, numbers)
print(list(result)) # [2, 4, 6]
Важная особенность: map() возвращает итератор (ленивое вычисление), а не список. Это экономит память для больших последовательностей.
Альтернатива — list comprehension (более Pythonic):
# map() версия
result = list(map(lambda x: x ** 2, [1, 2, 3, 4, 5]))
# List comprehension версия (рекомендуется)
result = [x ** 2 for x in [1, 2, 3, 4, 5]]
filter() — Выборка элементов
filter() оставляет только элементы, для которых функция возвращает True.
# Синтаксис: filter(function, iterable)
def is_even(x):
return x % 2 == 0
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
result = filter(is_even, numbers)
print(list(result)) # [2, 4, 6, 8, 10]
# С лямбда-функцией
result = filter(lambda x: x % 2 == 0, numbers)
print(list(result)) # [2, 4, 6, 8, 10]
# Фильтрация строк
words = ["python", "java", "c", "go", "rust"]
long_words = filter(lambda w: len(w) > 2, words)
print(list(long_words)) # ["python", "java", "rust"]
Если функция — None:
numbers = [0, 1, False, 2, "", 3, None, 4]
result = filter(None, numbers)
print(list(result)) # [1, 2, 3, 4] — убирает falsy значения
Как это работает внутри:
def my_filter(func, iterable):
"""Упрощённая реализация filter()"""
for item in iterable:
if func(item): # Проверяем условие
yield item
numbers = [1, 2, 3, 4, 5]
result = my_filter(lambda x: x > 2, numbers)
print(list(result)) # [3, 4, 5]
Альтернатива — list comprehension:
# filter() версия
result = list(filter(lambda x: x > 2, [1, 2, 3, 4, 5]))
# List comprehension версия (более Pythonic)
result = [x for x in [1, 2, 3, 4, 5] if x > 2]
reduce() — Сворачивание (accumulation)
reduce() комбинирует элементы последовательности в одно значение, применяя функцию кумулятивно.
⚠️ Важно: reduce() находится в модуле functools
from functools import reduce
# Синтаксис: reduce(function, iterable, [initializer])
def add(x, y):
return x + y
numbers = [1, 2, 3, 4, 5]
result = reduce(add, numbers)
print(result) # 15 (1+2+3+4+5)
# Эквивалент: 1 + 2 = 3, 3 + 3 = 6, 6 + 4 = 10, 10 + 5 = 15
# С лямбда-функцией
result = reduce(lambda x, y: x + y, numbers)
print(result) # 15
# С начальным значением (initializer)
result = reduce(lambda x, y: x + y, numbers, 100)
print(result) # 115 (100 + 1 + 2 + 3 + 4 + 5)
Как это работает внутри:
def my_reduce(func, iterable, initializer=None):
"""Упрощённая реализация reduce()"""
iterator = iter(iterable)
if initializer is None:
accumulator = next(iterator)
else:
accumulator = initializer
for value in iterator:
accumulator = func(accumulator, value)
return accumulator
numbers = [1, 2, 3, 4]
result = my_reduce(lambda x, y: x + y, numbers)
print(result) # 10
Практические примеры:
# Произведение чисел
from functools import reduce
numbers = [1, 2, 3, 4, 5]
product = reduce(lambda x, y: x * y, numbers)
print(product) # 120 (факториал 5)
# Нахождение максимума
from functools import reduce
numbers = [3, 1, 4, 1, 5, 9, 2, 6]
max_num = reduce(lambda x, y: x if x > y else y, numbers)
print(max_num) # 9
# Объединение словарей
from functools import reduce
dicts = [{"a": 1}, {"b": 2}, {"c": 3}]
merged = reduce(lambda x, y: {**x, **y}, dicts)
print(merged) # {"a": 1, "b": 2, "c": 3}
Цепочка: map → filter → reduce
Часто используются вместе:
from functools import reduce
# Задача: найти сумму квадратов чётных чисел
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
# Вариант 1: map → filter → reduce
result = reduce(
lambda x, y: x + y,
filter(
lambda x: True, # Все оставшиеся
map(
lambda x: x ** 2, # Возводим в квадрат
filter(
lambda x: x % 2 == 0, # Только чётные
numbers
)
)
)
)
print(result) # 2^2 + 4^2 + 6^2 + 8^2 + 10^2 = 4 + 16 + 36 + 64 + 100 = 220
# Вариант 2: List comprehension (более читаемо)
result = sum(x ** 2 for x in numbers if x % 2 == 0)
print(result) # 220
map() vs. filter() vs. List Comprehension
| Функция | Пример | Когда использовать |
|---|---|---|
| map() | map(str, [1, 2, 3]) | Преобразование типов, редко (list comprehension лучше) |
| filter() | filter(lambda x: x > 0, nums) | Фильтрация, редко (list comprehension лучше) |
| reduce() | reduce(lambda x, y: x+y, nums) | Аккумуляция, свёртка данных |
| List comprehension | [x*2 for x in nums] | РЕКОМЕНДУЕТСЯ для map и filter |
Ленивое вычисление (Lazy Evaluation)
map() и filter() возвращают итераторы, а не списки:
# Это НЕ вычисляется сразу!
result = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print(type(result)) # <class "map object">
# Вычисление происходит при итерации
for value in result:
print(value) # 1, 4, 9, 16, 25
# Или при конвертации в список
result = list(map(lambda x: x ** 2, [1, 2, 3]))
print(result) # [1, 4, 9]
Это экономит память для больших данных!
Заключение
- map() преобразует каждый элемент
- filter() выбирает элементы по условию
- reduce() сворачивает последовательность в одно значение
- В Python рекомендуется использовать list comprehension вместо map/filter для читаемости
- reduce() полезен для аккумуляции и свёртки данных
- Все возвращают итераторы (ленивое вычисление) — это экономит память