在python中创build一个列表的所有可能的组合
我需要能够创build一个包含input列表的所有可能组合的列表。 例如,列表[1,2,3]应该返回[1 [1,2] [1,3] 2 [2,3] 3 [1,2,3]]列表不一定要在特定的顺序。 在这个网站上,我发现了很多使用itertools的函数,但是当我只需要一个列表时,这些函数就是返回对象。 我是一个Python编码的初学者,所以任何想法或想法将不胜感激。
只需使用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]]
你可以在循环中使用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]]
编辑:组合的第一个参数是可迭代的,第二个是所得元组的长度(在这种情况下,从1
到len(l)
)。
有关组合的更多信息: http : //docs.python.org/library/itertools.html#itertools.combinations
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]]
或者将单个项目保留为列表:
out_list = map(list, out_list)
itertools
模块确实返回生成器而不是列表,但是:
- 生成器通常比列表更有效率(特别是如果您生成大量的组合)
- 当你真的需要的时候,你总是可以使用
list(...)
将生成器转换为列表 。
itertools
的chain
和combinations
函数运行良好 ,但是您需要使用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]]
如果您之前没有使用过生成器,请注意您将它们循环,就好像它们是列表一样,例如:
# 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) """
性能差异可能很大。 如果您比较性能,您会看到生成器的创build速度要快得多:
# 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
请注意,无论在哪种情况下都要花费一些时间来遍历所有的组合,但是对于您来说这可能是一个巨大的胜利,特别是如果您在早期find您想要的内容的话。