Комбинации элементов из нескольких списков в Python

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Если вам нужно сгенерировать все комбинации из списка списков в Python, рекомендуется использовать itertools.product. Этот метод формирует декартово произведение, в результате которого на выходе мы получаем кортежи с элементами из каждого списка.

Вот пример кода для генерации кортежей:

Python
Скопировать код
from itertools import product

lists = [[1, 2], [3, 4], [5, 6]]
print(list(product(*lists)))  # распаковка списков для передачи в itertools.product

Вы получите следующие кортежи:

[(1, 3, 5), ..., (2, 4, 6)]

Просто замените lists на собственные данные, запустите скрипт, и наслаждайтесь результатом!

Кинга Идем в IT: пошаговый план для смены профессии

Управление крайними случаями и эффективность использования itertools

А как быть с такими ситуациями, как пустые списки? itertools.product прекрасно справляется и с ними, эффективно обеспечивая обработку без лишнего проблемного дебага.

При работе с большим объемом данных критична производительность. Благодаря реализации на языке C в Python sklearn, itertools.product значительно повышает скорость исполнения кода.

Использование рекурсии при отсутствии itertools

Если в вашем распоряжении нет itertools, вы можете использовать рекурсию для реализации своего собственного генератора комбинаций:

Python
Скопировать код
def combine(list_of_lists, prefix=[]):
    if not list_of_lists:
        yield tuple(prefix)
    else:
        for item in list_of_lists[0]:
            yield from combine(list_of_lists[1:], prefix + [item])

# Пример использования:
for combination in combine([[1,2], [3], [4,5]]):
    print(combination)

Такой подход устраняет зависимости от сторонних библиотек и подойдёт даже для старых версий Python, где модуля itertools еще не предусмотрено.

Вариант с вложенными циклами

Иногда, для формирования сочетаний элементов из списков, вполне достаточно использовать вложенные циклы, без прибегания к itertools или рекурсии:

Python
Скопировать код
lists = [[1, 2], [3, 4], [5, 6]]
combinations = []

for a in lists[0]:
    for b in lists[1]:
        for c in lists[2]:
            combinations.append((a, b, c))
print(combinations)

Однако использование вложенных циклов делает код менее универсальным и элегантным по сравнению с itertools.product.

Решение при помощи Numpy для работы с числовыми данными

Если вы работаете с числами, можно воспользоваться Numpy и его методами numpy.meshgrid и numpy.reshape, чтобы получить комбинации в виде массивов:

Python
Скопировать код
import numpy as np

lists = [np.array(x) for x in [[1, 2], [3, 4], [5, 6]]]
mesh = np.meshgrid(*lists)
combinations = np.vstack(map(np.ravel, mesh)).T
print(combinations.tolist())

Данное решение отлично подходит для больших числовых расчетов, требующих высокой скорости исполнения, которую обеспечивает NumPy.

Работаем с разнообразием структур данных

У вас нет причин для беспокойства, если вам нужно создать комбинации различных типов данных, таких как строки и числа. itertools.product и пользовательская рекурсия без особых усилий выполнит эту задачу:

Python
Скопировать код
from itertools import product

lists = [['apple', 'banana'], [1, 2, 3], ['x', 'y']]
print(list(product(*lists)))

Достраиваем результат под ваши потребности

Если вам нужен конкретный формат вывода, например, список списков, Вы можете легко его получить, обернув вызов функции product в генератор списков:

Python
Скопировать код
from itertools import product

lists = [[1, 2], [3, 4], [5, 6]]
combinations = [list(combination) for combination in product(*lists)]
print(combinations)

Визуализация

Попробуем посмотреть на это все наглядно. Вообразите шеф-повара 👨‍🍳 с тремя полками ингредиентов:

Полка 1: [🍅, 🍆] Полка 2: [🧀, 🥚] Полка 3: [🌿, 🌶️]

Для приготовления блюда шеф-повару необходим по одному ингредиенту с каждой полки.

Python
Скопировать код
from itertools import product

# Функция `product` в Python, как шеф-повар, выбирает по одному ингредиенту с каждой полки.

Итак, результат:

🍅🧀🌿🍅🧀🌶️🍅🥚🌿🍅🥚🌶️
🍆🧀🌿🍆🧀🌶️🍆🥚🌿🍆🥚🌶️

Каждая строка таблицы — это готовый набор ингредиентов для блюда! 🍽️

Метод с использованием yield

Рассмотрим еще одну реализацию, которая тоже позволяет получить все возможные комбинации:

Python
Скопировать код
def all_combinations(lists):
    if len(lists) == 1:
        for item in lists[0]:
            yield (item,)
    else:
        for item in lists[0]:
            for rest in all_combinations(lists[1:]):
                yield (item,) + rest

# Пример использования:
for combination in all_combinations([[1,2], [3,4], [5,6]]):
    print(combination)

Работаем с большим количеством данных: переменное количество списков

Важно подчеркнуть, что как itertools.product, так и рекурсия прекрасно работают не только с двумя, но и с тысячами списков. Главное — корректно использовать распаковку аргументов (*) с itertools или обеспечить правильные рекурсивные вызовы и базовые условия.

Такой подход позволит вам справиться с данными любого объема и типа, при этом сохраняя гибкость и элегантность своего решения.

Полезные материалы

  1. itertools — Функции создания итераторов для эффективного циклического перебора — Python 3.12.2 документация — официальная документация Python по itertools.product().
  2. More Itertools — more-itertools 10.2.0 документация — расширенные инструменты итерации, которые дополняют itertools.
  3. Itertools в Python 3, На практике – Real Python — практические примеры использования itertools в Python.
  4. Python – Itertools.Product() – GeeksforGeeks — статья, подробно объясняющая использование itertools.product() для нахождения декартового произведения.
  5. Функции стандартной библиотеки Python | Programiz — подробное руководство по функции itertools.product().