Как можно использовать лямбда-выражение в конструкциях `reduce()` и `filter()` для работы с двумя списками одновременно?

Лямбда-выражения в reduce() и filter() обычно применяются к одному итерируемому объекту. Для работы с двумя списками одновременно необходимо предварительно их объединить в один итерируемый объект, например, список кортежей, используя zip(). Затем, лямбда-выражение будет обрабатывать элементы этих кортежей.

Пример filter():

  list1 = [1, 2, 3, 4, 5]
  list2 = [6, 7, 8, 9, 10]

  # Отфильтровать элементы, где сумма больше 10
  filtered_list = list(filter(lambda x: x[0] + x[1] > 10, zip(list1, list2)))
  # filtered_list будет: [(3, 8), (4, 9), (5, 10)]
  
Пример reduce():

  from functools import reduce

  list1 = [1, 2, 3]
  list2 = [4, 5, 6]

  # Сумма произведений элементов соответствующих индексов
  result = reduce(lambda acc, x: acc + (x[0] * x[1]), zip(list1, list2), 0)
  # result будет: 1*4 + 2*5 + 3*6 = 4 + 10 + 18 = 32
  
В этих примерах zip(list1, list2) создает итератор кортежей, а лямбда-выражение оперирует элементами внутри каждого кортежа.

Лямбда-выражения в Python - это анонимные функции, которые могут быть использованы для создания кратких и лаконичных операций. Они особенно полезны в сочетании с функциями высшего порядка, такими как reduce() и filter().

Использование с filter():

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

Чтобы использовать filter() с двумя списками, нужно создать условие, которое сравнивает элементы из обоих списков. Обычно это делается, создавая список кортежей из элементов двух списков (например, с помощью zip()) и затем применяя filter() к этому списку кортежей.

Пример:


from functools import reduce

list1 = [1, 2, 3, 4, 5]
list2 = [6, 2, 8, 4, 9]

# Найти элементы, которые присутствуют в обоих списках (индексы не важны)
common_elements = list(filter(lambda x: x in list2, list1))
print(f"Элементы, присутствующие в обоих списках: {common_elements}") # Вывод: [2, 4]

# Отфильтровать пары, где элементы равны (по индексу)
paired_lists = list(zip(list1, list2))
equal_pairs = list(filter(lambda pair: pair[0] == pair[1], paired_lists))
print(f"Пары с равными элементами: {equal_pairs}") # Вывод: [(2, 2), (4, 4)]

# Отфильтровать элементы list1, которые больше соответствующих элементов list2
greater_elements = list(filter(lambda pair: pair[0] > pair[1], zip(list1, list2)))
print(f"Элементы list1 больше list2: {greater_elements}") # Вывод: [(3, 2), (5, 4)]
  

Использование с reduce():

Функция reduce() (из модуля functools) последовательно применяет функцию (в нашем случае, лямбда-выражение) к элементам итерируемого объекта, "сводя" его к одному значению. Лямбда-выражение должно принимать два аргумента: аккумулятор и следующий элемент итерируемого объекта.

При работе с двумя списками, опять же, обычно создается список кортежей. Лямбда-выражение в reduce() оперирует этими кортежами для достижения определенного результата.

Пример:


from functools import reduce

list1 = [1, 2, 3, 4, 5]
list2 = [6, 2, 8, 4, 9]

# Найти сумму произведений соответствующих элементов
product_sum = reduce(lambda acc, pair: acc + pair[0] * pair[1], zip(list1, list2), 0)
print(f"Сумма произведений: {product_sum}") # Вывод: 70

# Найти максимальную разницу между соответствующими элементами
max_diff = reduce(lambda acc, pair: max(acc, abs(pair[0] - pair[1])), zip(list1, list2), 0)
print(f"Максимальная разница: {max_diff}") # Вывод: 5

# Найти минимальный элемент из попарных сумм элементов из list1 и list2
min_sum = reduce(lambda acc, pair: min(acc, pair[0] + pair[1]), zip(list1, list2), float('inf'))
print(f"Минимальная сумма: {min_sum}") # Вывод: 4
  

Важно: Использование zip() гарантирует, что обработка будет идти только до тех пор, пока не закончится один из списков. Если списки имеют разную длину, "лишние" элементы более длинного списка будут проигнорированы. Если требуется иная логика обработки списков разной длины, необходимо использовать другие подходы, такие как itertools.zip_longest().

0