2014-03-06 64 views
1

我能有感谢名单的笛卡尔积到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 

回答

3
>>> 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')] 
+0

我误解组合的第二个论点的目的()到期到文档在其示例中使用字符串作为迭代的事实。有一个明显的方法来做到这一点。谢谢。我想我可以通过限制范围来设置最大尺寸。 – Sildar

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') 
+0

虽然我发现你处理开始/停止的方式有点奇怪,但你的回答基本上得出了相同的结论:“使用组合的第二个参数”。您的答案提供了一个功能,可以轻松设置最小值和最大值。但是,我不应该根据我的数据设置不同的最小/最大值,并且可以通过在范围内调用min(maxsize,len(lists))来限制它。 Thx为您的答案和演示:) – Sildar

+0

@sildar:'start'和'stop'处理是基于'range()'如何处理这个问题,但在这种情况下它可能会过于复杂一点。我会简化。 –