笛卡尔积不同的产品

时间:2014-03-06 10:30:17

标签: python list itertools

由于itertools.product()函数,我可以拥有列表的笛卡尔积:

lists = [['A', 'B'], ['1', '2'], ['x', 'y']]
combinations = itertools.product(*lists)
# [('A', '1', 'x'), ('A', '2', 'y'), ..., ('B', '2', 'y')]

我想要的是同样的东西,但有各种不同的尺寸:

all_comb = magicfunction(lists)
# [('A', '1', 'x'), ..., ('B', '2', 'y'), ('A', '1'), ('A', '2'), ... ('2', 'y'), ... ('y')]

我看不出一种明显的方法。

我需要一种方法可以让我设置元组的最小和最大大小(我处理长列表,只需要从7到3的大小组合,列表的数量和它们的大小不同)。

我的名单更像是:

lists = [['A', 'B', 'C'], ['1', '2'], ['x', 'y', 'z', 'u'], ...] # size may go to a few dozens

2 个答案:

答案 0 :(得分:4)

>>> from itertools import product, combinations
>>> lists = [['A', 'B'], ['1', '2'], ['x', 'y']]
>>> for i in xrange(2, len(lists)+1):
    for c in combinations(lists, i):
        print list(product(*c))
...         
[('A', '1'), ('A', '2'), ('B', '1'), ('B', '2')]
[('A', 'x'), ('A', 'y'), ('B', 'x'), ('B', 'y')]
[('1', 'x'), ('1', 'y'), ('2', 'x'), ('2', 'y')]
[('A', '1', 'x'), ('A', '1', 'y'), ('A', '2', 'x'), ('A', '2', 'y'), ('B', '1', 'x'), ('B', '1', 'y'), ('B', '2', 'x'), ('B', '2', 'y')]

答案 1 :(得分:2)

根据较小尺寸的组合将几种产品链接在一起:

from itertools import chain, product, combinations

def ranged_product(*lists, **start_stop):
    start, stop = start_stop.get('start', len(lists)), start_stop.get('stop', 0)
    return chain.from_iterable(product(*comb)
                               for size in xrange(start, stop - 1, -1)
                               for comb in combinations(lists, r=size))

演示:

>>> lists = [['A', 'B'], ['1', '2'], ['x', 'y']]
>>> for prod in ranged_product(stop=2, *lists):
...     print prod
... 
('A', '1', 'x')
('A', '1', 'y')
('A', '2', 'x')
('A', '2', 'y')
('B', '1', 'x')
('B', '1', 'y')
('B', '2', 'x')
('B', '2', 'y')
('A', '1')
('A', '2')
('B', '1')
('B', '2')
('A', 'x')
('A', 'y')
('B', 'x')
('B', 'y')
('1', 'x')
('1', 'y')
('2', 'x')
('2', 'y')