2011-12-03 70 views
31

我需要能够创建一个包含输入列表的所有可能组合的列表。 例如,列表[1,2,3]应该返回[1 [1,2] [1,3] 2 [2,3] 3 [1,2,3]] 列表不必是以任何特定的顺序。在这个网站上,我发现了很多使用itertools的函数,但是当我只需要一个列表时,这些函数就会返回对象。我是一名编码python的初学者,所以任何想法或想法都将不胜感激。在python中创建列表的所有可能组合

回答

40

只需使用itertools.combinations。例如:

import itertools 

lst = [1, 2, 3] 
combs = [] 

for i in xrange(1, len(lst)+1): 
    combs.append(i) 
    els = [list(x) for x in itertools.combinations(lst, i)] 
    combs.append(els) 

现在combs保持此值:

[1, [[1], [2], [3]], 2, [[1, 2], [1, 3], [2, 3]], 3, [[1, 2, 3]]] 

是的,这是从您提供的样本输出略有不同,但在输出你没有列出所有可能的组合。

我列出组合的大小前的实际列表中为每个大小,如果你需要的是简单的组合(不包括大小,因为它出现在你的样品输出),那么请尝试以下其他版本验证码:

import itertools 

lst = [1, 2, 3] 
combs = [] 

for i in xrange(1, len(lst)+1): 
    els = [list(x) for x in itertools.combinations(lst, i)] 
    combs.extend(els) 

现在combs保持此值:

[[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 
+0

我导入itertools命令使用 >>> from itertools import * 但我的解释器告诉我itertools没有定义。 对不起,所有简单的问题,我只是非常新的python和编程一般。 – Charles

+0

这不是OP要求的。 – juliomalegria

+0

@ julio.alegria是的,这就是OP的要求,我刚刚编辑我的回答 –

5

从itertools模块里返回迭代器的功能。您只需将结果转换成列表list()即可。但是,由于您需要拨打itertools.combinations三个不同的时间(每个不同长度一次),您可以使用list.extend将迭代器的所有元素添加到最终列表中。

尝试以下操作:

import itertools 
in_list = [1, 2, 3] 
out_list = [] 
for i in range(1, len(in_list)+1): 
    out_list.extend(itertools.combinations(in_list, i)) 

或列表的理解:

out_list = [c for i in range(len(in_list)) for c in itertools.combinations(in_list, i+1)] 

这将导致以下列表:

[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 

如果想列出,而不是元组,并将单个长度元组转换为值,您可以执行以下操作:

out_list = [x[0] if len(x) == 1 else list(x) for x in out_list] 
# [1, 2, 3, [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

或者离开单一的项目,如列表:

+0

我试过用这个,但口译员说我可以不要在NoneTypes上使用它。 – Charles

+0

你的两个解决方案仍然返回元组列表。 – juliomalegria

+0

是的,我需要列表的列表,而不是元组。有没有办法解决这个问题,而不使用itertools? – Charles

5

你可以解决一个循环内使用itertools.combinations您的问题:

>>> l = [1,2,3] 
>>> comb = [] 
>>> for i in range(len(l)): 
... comb += itertools.combinations(l,i+1) 
... 
>>> comb 
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 

如果你希望他们作为一个列表:

>>> comb_list = [ list(t) for t in comb ] 
>>> comb_list 
[[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

编辑:组合的第一个参数是可迭代的,第二个参数是所得元组的长度(在这种情况下,从1len(l))。

更多关于组合:http://docs.python.org/library/itertools.html#itertools.combinations

6

itertools模块确实返回发电机而不是列表,而是:

  • 发电机往往比列表(特别是如果你产生了大量的更有效组合)
  • 当您真的需要时,您始终可以使用list(...)将生成器转换为列表。

itertools工作做好chaincombinations功能,但你需要使用的Python 2.6或更高版本:

import itertools 

def all_combinations(any_list): 
    return itertools.chain.from_iterable(
     itertools.combinations(any_list, i + 1) 
     for i in xrange(len(any_list))) 

然后,您可以调用该如此:

# as a generator 
all_combinations([1,2,3]) # --> <itertools.chain at 0x10ef7ce10> 

# as a list 
list(all_combinations([1,2,3])) # --> [(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)] 

# as a list of lists 
[list(l) for l in all_combinations([1,2,3])] # --> [[1], [2], [3], [1, 2], [1, 3], [2, 3], [1, 2, 3]] 

如果您之前没有使用过发电机,请注意您将它们循环,就好像它们是一个lis t,如:

# a generator returned instead of list 
my_combinations = all_combinations([1,2,3]) 

# this would also work if `my_combinations` were a list 
for c in my_combinations: 
    print "Combo", c 

""" 
Prints: 
    Combo (1,) 
    Combo (2,) 
    Combo (3,) 
    Combo (1, 2) 
    Combo (1, 3) 
    Combo (2, 3) 
    Combo (1, 2, 3) 
""" 

性能差异可能很大。如果你比较性能,你会看到,发电机快得多创建:

# as a generator 
all_combinations(range(25)) # timing: 100000 loops, best of 3: 2.53 µs per loop 

# as a list 
list(all_combinations(range(25))) # timing: 1 loops, best of 3: 9.37 s per loop 

注意,它仍然需要一段时间,通过在任何情况下,所有的组合迭代,但它可以是一个大为你赢得胜利,特别是如果你在早期找到你想要的东西的话。

1
l = [1,2,3] 
combs = reduce(lambda x, y: list(itertools.combinations(l, y)) + x, range(len(l)+1), []) 

如果你想要一个oneliner。

相关问题