2014-03-06 87 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()'如何處理這個問題,但在這種情況下它可能會過於複雜一點。我會簡化。 –