优雅的方式来获得迭代列表的组合

优雅的方式来获得迭代列表的组合

问题描述:

我有一个可迭代对象的列表,我有兴趣获得由每个迭代组成的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

[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

这就是我想出了...

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