У меня есть пулы значений, и я хотел бы генерировать все возможные неупорядоченные комбинации, выбирая из определенных пулов.
Например, я хотел выбрать из пула 0, пула 0 и пула 1:
>>> pools = [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
>>> part = (0, 0, 1)
>>> list(product(*(pools[i] for i in part)))
[(1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 2), (1, 3, 3), (1, 3, 4), (2, 1, 2), (2, 1, 3), (2, 1, 4), (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 2), (2, 3, 3), (2, 3, 4), (3, 1, 2), (3, 1, 3), (3, 1, 4), (3, 2, 2), (3, 2, 3), (3, 2, 4), (3, 3, 2), (3, 3, 3), (3, 3, 4)]
Это генерирует все возможные комбинации путем выбора из пула 0, пула 0 и пула 1.
Однако порядок не имеет значения для меня, поэтому многие из комбинаций на самом деле дублируются. Например, поскольку я использовал декартово произведение, генерируются как (1, 2, 4)
и (2, 1, 4)
.
Я придумал простой способ смягчить эту проблему. Для участников, выбранных из одного пула, я выбираю без упорядочения с помощью combinations_with_replacement
. Я подсчитываю, сколько раз я хочу рисовать из каждого пула. Код выглядит так:
cnt = Counter()
for ind in part: cnt[ind] += 1
blocks = [combinations_with_replacement(pools[i], cnt[i]) for i in cnt]
return [list(chain(*combo)) for combo in product(*blocks)]
Это уменьшает порядок дублирования, если я случайно несколько раз выбираю один и тот же пул. Однако все пулы имеют много перекрытий, и использование combinations_with_replacement
при combinations_with_replacement
нескольких пулов приведет к созданию некорректных комбинаций. Существует ли более эффективный метод генерации неупорядоченных комбинаций?
Изменение: Дополнительная информация о входах: количество частей и пулов невелико (~ 5 и ~ 20), и для простоты каждый элемент является целым числом. Фактическая проблема, которую я уже решил, так это просто для академического интереса. Скажем, в каждом пуле есть тысячи сотен целых чисел, но некоторые пулы небольшие и имеют только десятки. Таким образом, какой-то союз или пересечение, похоже, это путь.