使用 itertools 从列表中进行组合

Making Combination from lists using itertools

import itertools
a = [[2, 3], [3, 4]]
b = [[5, 6], [7, 8], [9, 10]]
c = [[11, 12], [13, 14]]
d = [[15, 16], [17, 18]]
e = [[12,16],[13,17],[14,18],[15,19]]

q=[]
q=list(itertools.combinations((a, b, b,c, c, d,e),7)
print q

如何正确使用 itertools 中的组合函数来使用列表 a 一次,b 2 次无替换,c 2 次无替换,d 和 e 各一次?

[[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[12,16]], 
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[13,17]],
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[14,18]],
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[15,19]], 
[[2, 3],[5, 6],[7, 8],[11, 12],[13, 14],[15, 16],[12,16]],...
[[3, 4],[7, 8],[9, 10],[11, 12], [13, 14],[17, 18],[15,19]]]

已更新,说明了预期输出

You want itertools.product:

itertools.product(a, b, b, c, c, c, c, d, e)

它会在每次迭代时从它的每个参数中选择一个元素,循环最右边的元素最快,最左边的元素最慢。

在Python 3:

中,您可以使用扩展参数解包来更明显地表达某些参数的重复
itertools.product(a, *[b]*2, *[c]*4, d, e)

或使用 进行更一般的序列重复(这也适用于 Py2)。

您似乎在寻找 combinations and product 的组合:使用 combinations 获得可能的组合而不替换重复的列表,然后使用 product 组合所有这些组合。您可以将列表和计数放在两个列表中,zip 那些列表,并使用生成器表达式来获取所有组合。

from itertools import product, combinations, chain
lists = [a,b,c,d,e]
counts = [1,2,2,1,1]
combs = product(*(combinations(l, c) for l, c in zip(lists, counts)))

对于此示例,combs 生成器有 48 个元素,其中包括:

[(([2, 3],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([15, 16],), ([12, 16],)),
 ...
 (([2, 3],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([17, 18],), ([15, 19],)),
 (([2, 3],), ([5, 6], [9, 10]),([11, 12], [13, 14]), ([15, 16],), ([12, 16],)),
 ...
 (([3, 4],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([15, 16],), ([12, 16],)),
 ...
 (([3, 4],), ([5, 6], [7, 8]), ([11, 12], [13, 14]), ([17, 18],), ([15, 19],)),
 ...
 (([3, 4],), ([7, 8], [9, 10]),([11, 12], [13, 14]), ([17, 18],), ([15, 19],))]

如果你想要 flattened lists, just chain 他们:

>>> combs = (list(chain(*p)) for p in product(*(combinations(l, c) for l, c in zip(lists, counts))))
>>> list(combs)
[[[2, 3], [5, 6], [7, 8], [11, 12], [13, 14], [15, 16], [12, 16]],
 ...
 [[3, 4], [7, 8], [9, 10], [11, 12], [13, 14], [17, 18], [15, 19]]]

您要实现的是 Cartesian product of input iterables 而不是列表中项目的组合。因此,您必须改用 itertools.product()

如果多次使用的列表允许重复,答案很简单:

>>> import itertools
>>> a = [1,2]
>>> b = [3,4]
>>> [i for i in itertools.product(a, b, b)]
[(1, 3, 3), (1, 3, 4), (1, 4, 3), (1, 4, 4), (2, 3, 3), (2, 3, 4), (2, 4, 3), (2, 4, 4)]

但是如果 repetition is not allowed 在同一个列表中,它会变得有点讨厌,你需要将上面的答案与 combinations() and chain() (same as mentioned by tobias_k) 结合起来。此代码将给出所有 combinations:

的列表
>>> from itertools import chain, product, combinations
>>> lists, counts = [a, b], [1, 2]  # to track that a is to be used once, and b twice
>>> list(list(chain(*p)) for p in product(*(combinations(l, c) for l, c in zip(lists, counts))))
[[1, 3, 4], [2, 3, 4]]

但是,如果您需要排列而不是组合,则必须使用 permutations():

更新上述代码
>>> from itertools import chain, product, permutations
>>> list(list(chain(*p)) for p in product(*(permutations(l, c) for l, c in zip(lists, counts))))
[[1, 3, 4], [1, 4, 3], [2, 3, 4], [2, 4, 3]]