笛卡尔积,返回不同长度的输出

时间:2015-03-05 05:28:39

标签: python list python-3.x itertools cartesian-product

所以我有这些清单:

a = [1, 2, 3]
b = [11, 12, 13, 14]
c = [21, 22, 23, 24, 25, 26]

我希望获得所有可能的组合(重复都很好),包括来自a的2个元素,来自b的3个元素和来自c的3个元素 。像这样:

([1, 2], [11, 12, 13], [21, 22, 23]) # 1
([1, 2], [11, 12, 13], [22, 23, 24]) # 2
# all the way to...
([2, 3], [12, 13, 14], [24, 25, 26]) # 16

如果我使用itertools.product(),它只会从每个列表中给我1个:

import itertools

def cartesian(the_list):
    for i in itertools.product(*the_list):
        yield i

a = [1, 2, 3]
b = [11, 12, 13, 14]
c = [21, 22, 23, 24, 25, 26]

test = cartesian([a, b, c])

print(next(test)) 
# Gives (1, 11, 21). But I need ([1, 2], [11, 12, 13], [21, 22, 23])

print(next(test)) 
# Gives (1, 11, 22). But I need ([1, 2], [11, 12, 13], [22, 23, 24])

我可以使用多个嵌套的for循环,但如果我有很多列表,我需要太多的循环。

那么我该如何实现一个算法,它给出了所有可能的组合,每个组合由每个输入列表中的一定数量的元素组成?

1 个答案:

答案 0 :(得分:5)

构建一个生成器函数,可以生成任意数量的值并在product中使用它,就像这样

>>> from itertools import product
>>> def get_chunks(items, number=3):
...     for i in range(len(items) - number + 1): 
...         yield items[i: i + number]
...     
... 

然后定义您的cartesian生成器,就像这样

>>> def cartesian(a, b, c):
...     for items in product(get_chunks(a, 2), get_chunks(b), get_chunks(c)):
...         yield items
...     
... 

如果你使用的是Python 3.3+,你可以在这里使用yield from,就像这样

>>> def cartesian(a, b, c):
...     yield from product(get_chunks(a, 2), get_chunks(b), get_chunks(c))
... 

然后,当您将所有元素作为列表获取时,您将获得

>>> from pprint import pprint
>>> pprint(list(cartesian([1, 2, 3],[11, 12, 13, 14],[21, 22, 23, 24, 25, 26])))
[([1, 2], [11, 12, 13], [21, 22, 23]),
 ([1, 2], [11, 12, 13], [22, 23, 24]),
 ([1, 2], [11, 12, 13], [23, 24, 25]),
 ([1, 2], [11, 12, 13], [24, 25, 26]),
 ([1, 2], [12, 13, 14], [21, 22, 23]),
 ([1, 2], [12, 13, 14], [22, 23, 24]),
 ([1, 2], [12, 13, 14], [23, 24, 25]),
 ([1, 2], [12, 13, 14], [24, 25, 26]),
 ([2, 3], [11, 12, 13], [21, 22, 23]),
 ([2, 3], [11, 12, 13], [22, 23, 24]),
 ([2, 3], [11, 12, 13], [23, 24, 25]),
 ([2, 3], [11, 12, 13], [24, 25, 26]),
 ([2, 3], [12, 13, 14], [21, 22, 23]),
 ([2, 3], [12, 13, 14], [22, 23, 24]),
 ([2, 3], [12, 13, 14], [23, 24, 25]),
 ([2, 3], [12, 13, 14], [24, 25, 26])]