У меня есть список с 15 числами, и мне нужно написать некоторый код, который производит все 32 768 комбинаций этих чисел.
Я нашел некоторый код (от Googling), который, очевидно, делает то, что я ищу, но я нашел код довольно непрозрачным и опасаюсь его использовать. Плюс у меня такое ощущение, что должно быть более элегантное решение.
Единственное, что приходит мне в голову, - это просто перебирать десятичные целые числа 1–32768 и преобразовывать их в двоичные, а также использовать двоичное представление в качестве фильтра для выбора соответствующих чисел.
Кто-нибудь знает лучший способ? Используя map()
, может быть?
product
и т. Д.)Ответы:
Посмотрите на itertools.combinsk :
Начиная с 2.6, батареи включены!
источник
list(itertools.combinations(iterable, r))
r
, т.е. комбинации подпоследовательностей любой длины элементов.В этом ответе пропущен один аспект: ОП запросил ВСЕ комбинации ... а не только комбинации длины "r".
Таким образом, вы либо должны пройти через все длины "L":
Или - если вы хотите быть привлекательным (или склонить голову над тем, кто читает ваш код после вас) - вы можете сгенерировать цепочку генераторов "комбинаций ()" и выполнить итерацию:
источник
powerset()
функция генератора в разделе рецептовitertools
документации проще, потенциально использует меньше памяти и, вероятно, быстрее, чем реализация, показанная здесь.itertools.combinations
сохраняет порядок элементов в списках, которые он выдает. Таким образом, если вход отсортирован по лексическому принципу, то каждый из выходов также будет.itertools.combinations
генерирует комбинации k среди n в лексикографическом порядке, но не все комбинации до k среди n.powerset
генерирует все комбинации вплоть до k, но не в лексикографическом порядке, насколько я понимаю: powerset ([1,2]) -> [(), (1,), (2,), (1, 2)] , Разве это не должно быть: [(), (1,), (1, 2), (2,)]?Вот ленивый однострочный, также использующий itertools:
Основная идея этого ответа: есть 2 ^ N комбинаций - столько же, сколько двоичных строк длины N. Для каждой двоичной строки вы выбираете все элементы, соответствующие «1».
Что нужно учитывать:
len(...)
наitems
(обходной путь: еслиitems
что - то вроде итератора как генератор, превратить его в список первых сitems=list(_itemsArg)
)items
не был случайным (обходной путь: не будьте безумным){2,2,1}
и{2,1,1}
будет как коллапс в{2,1}
(обходной: использование вcollections.Counter
качестве дроп-ин для заменыset
, это в основном мультимножеством ... хотя вам может понадобиться более позднего использования ,tuple(sorted(Counter(...).elements()))
если вам это нужно , чтобы быть hashable)демонстрация
источник
В комментариях под высоко голосуемым ответом @Dan H упоминается
powerset()
рецепт вitertools
документации, включая рецепт самого Дэна . Однако до сих пор никто не опубликовал это как ответ. Так как это, вероятно, один из лучших, если не лучший подход к проблеме - и с небольшой поддержкой другого комментатора, он показан ниже. Функция создает все уникальные комбинации элементов списка любой возможной длины (включая те, которые содержат ноль и все элементы).Примечание . Если цель, которая немного отличается, состоит в том, чтобы получить только комбинации уникальных элементов, измените строку
s = list(iterable)
на,s = list(set(iterable))
чтобы исключить дублирование элементов. Независимо от того факта, что вiterable
конечном итоге он превращается вlist
средство, он будет работать с генераторами (в отличие от некоторых других ответов).Вывод:
источник
list()
нужна конверсия?Вот один из них, использующий рекурсию:
источник
new_data = copy.copy(data)
- насколько я вижу, этот ряд избыточен, ни на что не влияетЭтот однострочник дает вам все комбинации (между
0
иn
элементами, если исходный список / набор содержитn
отдельные элементы) и использует собственный методitertools.combinations
:Python 2
Python 3
Выход будет:
Попробуйте онлайн:
http://ideone.com/COghfX
источник
['b', 'a']
.TypeError: can only concatenate list (not "map") to list
Я согласен с Дэном Х., что Бен действительно просил все комбинации.
itertools.combinations()
не дает всех комбинаций.Другая проблема в том, что если итеративный ввод велик, возможно, лучше вернуть генератор вместо всего в списке:
источник
Это подход, который может быть легко перенесен на все языки программирования, поддерживающие рекурсию (без itertools, без yield, без понимания списка) :
источник
Вы можете создать все комбинации списка в Python, используя этот простой код
Результат будет:
источник
Я думал, что добавлю эту функцию для тех, кто ищет ответ без импорта itertools или каких-либо других дополнительных библиотек.
Простое использование генератора доходности:
Вывод из примера использования выше:
источник
Вот еще одно решение (однострочное), включающее использование
itertools.combinations
функции, но здесь мы используем понимание двойного списка (в отличие от цикла for или суммы):Демо-версия:
источник
вывод
источник
Ниже приведен «стандартный рекурсивный ответ», аналогичный другому аналогичному ответу https://stackoverflow.com/a/23743696/711085 . (На самом деле нам не нужно беспокоиться об исчерпании стекового пространства, поскольку мы не можем обработать все N! Перестановки.)
Он посещает каждый элемент по очереди и либо берет его, либо покидает его (мы можем непосредственно увидеть 2 ^ N мощности из этого алгоритма).
Демо-версия:
источник
Используя понимание списка:
Выход будет:
источник
Этот код использует простой алгоритм с вложенными списками ...
источник
""
).Я знаю, что гораздо более практично использовать itertools для получения всех комбинаций, но вы можете достичь этого частично только с помощью понимания списка, если вам так хочется, если вы хотите много кодировать
Для комбинаций двух пар:
А для комбинаций из трех пар это так просто:
Результат идентичен использованию itertools.combination:
источник
Без использования itertools:
источник
Вот две реализации
itertools.combinations
Тот, который возвращает список
Один возвращает генератор
Обратите внимание, что предоставление вспомогательной функции рекомендуется, поскольку аргумент prepend является статическим и не меняется при каждом вызове.
Это очень поверхностный случай, но лучше быть в безопасности, чем потом сожалеть
источник
Как насчет этого .. использовал строку вместо списка, но то же самое .. строку можно рассматривать как список в Python:
источник
Комбинация из itertools
Спасибо
источник
Без
itertools
в Python 3 вы можете сделать что-то вроде этого:где изначально
carry = "".
источник
3 функции:
источник
Это моя реализация
источник
Вы также можете использовать функцию powerset из отличного
more_itertools
пакета.Мы также можем убедиться, что он соответствует требованиям OP
источник
источник
Если кто-то ищет обратный список, как я:
источник
источник