2013-03-07 129 views
2

我有一個可迭代對象的列表,我有興趣獲得由每個迭代組成的0或1個項目的所有列表(順序不重要,所以它的組合不是排列組合我尋求)。優雅的方式來獲得迭代列表的組合

我有一個非常不雅的實現,我已經在下面發佈。

我相信有一種更優雅的方式來做到這一點,可能與itertools模塊,但我不能拿出任何東西。有什麼建議?


import itertools 


def all_subsets(ss): 
    subset_lens = range(0, len(ss) + 1) 
    list_of_subsets = map(lambda n: itertools.combinations(ss, n), subset_lens) 
    return itertools.chain.from_iterable(list_of_subsets) 


list_of_iterables = [["A1"], ["B1", "B2", "B3"], ["C1", "C2"]] 

all_possibilities = itertools.chain.from_iterable(itertools.product(*subset) 
           for subset in all_subsets(list_of_iterables)) 

# Visual representation of the desired result 
for eg in all_possibilities: 
    print eg 

結果:

() 
('A1',) 
('B1',) 
('B2',) 
('B3',) 
('C1',) 
('C2',) 
('A1', 'B1') 
('A1', 'B2') 
('A1', 'B3') 
('A1', 'C1') 
... 
+0

你只是對顯示結果感興趣,或者你還想要組合存儲嗎? – 2013-03-07 20:57:53

+0

@埃德加,我會做的事情超出了這個問題的範圍,所以我需要存儲,而不是打印。視覺表示只是爲了幫助解釋我的問題! – 2013-03-07 21:04:32

回答

1
[filter(None, comb) for comb in itertools.product(*[[None] + it for it in list_of_iterables])] 

這使得一對夫婦簡化假設。如果您的迭代器包含的值在布爾上下文中不是true,那麼您必須使用更復雜的filter。如果您的iterables不是列表,則必須使用itertools.chain而不是[None] + it

+0

我的迭代不是列表(我將使用'chain'),但是我已經在其中的每個對象上實現了__nonzero__。這非常有用,謝謝! – 2013-03-07 20:59:27

1

這就是我想出了...

data = [["A1"], ["B1", "B2", "B3"], ["C1", "C2"]] 
data = [[None] + x for x in data] 
data = sorted(filter(None, x) for x in itertools.product(*data)) 
for result in data: 
    print result 

輸出:

() 
('A1',) 
('A1', 'B1') 
('A1', 'B1', 'C1') 
('A1', 'B1', 'C2') 
('A1', 'B2') 
('A1', 'B2', 'C1') 
('A1', 'B2', 'C2') 
('A1', 'B3') 
('A1', 'B3', 'C1') 
('A1', 'B3', 'C2') 
('A1', 'C1') 
('A1', 'C2') 
('B1',) 
('B1', 'C1') 
('B1', 'C2') 
('B2',) 
('B2', 'C1') 
('B2', 'C2') 
('B3',) 
('B3', 'C1') 
('B3', 'C2') 
('C1',) 
('C2',) 
+2

嘿,和我的完全一樣,我們幾乎在同一瞬間發佈!融合思維! – BrenBarn 2013-03-07 20:55:18

+0

偉大的思想都相似! – FogleBird 2013-03-07 20:55:46

+1

或者它是Python的禪宗? 「應該有一個 - 而且最好只有一個 - 明顯的做法。」 – FogleBird 2013-03-07 20:56:23