简体   繁体   English

制作列表的所有可能组合

[英]Making all possible combinations of a list

I need to be able to make a list that contains all possible combinations of an inputted list.我需要能够制作一个包含输入列表的所有可能组合的列表。 For example the list [1,2,3] should return [1 [1,2] [1,3] 2 [2,3] 3 [1,2,3]] The list doesn't have to be in any particular order.例如列表[1,2,3]应该返回[1 [1,2] [1,3] 2 [2,3] 3 [1,2,3]]该列表不必在任何特定顺序。 On this site I've found lots of functions using the itertools but those are returning objects when I need just a list .在这个站点上,我发现了很多使用itertools的函数,但是当我只需要一个list时,它们会返回对象。

Simply use itertools.combinations .只需使用itertools.combinations For example:例如:

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)

Now combs holds this value:现在combs持有这个值:

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

Yes, it's slightly different from the sample output you provided, but in that output you weren't listing all possible combinations.是的,它与您提供的示例输出略有不同,但在该输出中您并未列出所有可能的组合。

I'm listing the size of the combination before the actual list for each size, if what you need is simply the combinations (without the size, as it appears in your sample output) then try these other version of the code:我在每个尺寸的实际列表之前列出了组合的尺寸,如果您需要的只是组合(没有尺寸,如您的示例输出中所示),请尝试这些其他版本的代码:

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)

Now combs holds this value:现在combs持有这个值:

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

The itertools module indeed returns generators instead of lists, but: itertools模块确实返回生成器而不是列表,但是:

  • Generators are often more efficient than lists (especially if you are generating a large number of combinations)生成器通常比列表更有效(尤其是在生成大量组合时)
  • You can always convert generators to lists using list(...) when you really need to.当您确实需要时,您始终可以使用list(...)将生成器转换为列表

The chain and combinations functions of itertools work well , but you need to use Python 2.6 or greater: itertoolschaincombinations函数运行良好,但需要使用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)))

You can then call this as such:然后你可以这样调用它:

# 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]]

If you haven't used generators before, note that you loop through them as if they were a list, such as this:如果您之前没有使用过生成器,请注意您将它们当作一个列表来循环,例如:

# 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)
"""

The performance difference can be dramatic.性能差异可能是巨大的。 If you compare the performance you'll see that the generator is much faster to create:如果比较性能,您会发现生成器的创建速度要快得多:

# 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

Note that it would still take some time to iterate through all the combinations in either case, but it can be a big win for you especially if you find what you're looking for early on.请注意,在任何一种情况下,遍历所有组合仍然需要一些时间,但这对您来说可能是一个巨大的胜利,尤其是如果您很早就找到了想要的东西。

The functions from the itertools module return iterators. itertools 模块中的函数返回迭代器。 All you need to do to convert these into lists is call list() on the result.将这些转换为列表所需要做的就是对结果调用list()

However, since you will need to call itertools.combinations three separate times (once for each different length), you can just use list.extend to add all elements of the iterator to your final list.但是,由于您需要调用itertools.combinations三次(每个不同的长度调用一次),因此您可以使用list.extend将迭代器的所有元素添加到最终列表中。

Try the following:请尝试以下操作:

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))

Or as a list comprehension:或者作为列表理解:

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

These will result in the following list:这些将导致以下列表:

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

If you want lists instead of tuples, and to convert the single length tuples to just the value, you can do the following:如果您想要列表而不是元组,并将单长度元组转换为值,您可以执行以下操作:

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]]

Or to leave the single items as lists:或者将单个项目保留为列表:

out_list = map(list, out_list)

You could solve your problem using itertools.combinations inside of a loop:您可以在循环内使用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)]

And if you want them as a list:如果您希望将它们作为列表:

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

EDIT: The first parameter of combinations is the iterable and the second one is the length of the resulting tuples (in this case, going from 1 to len(l) ).编辑:组合的第一个参数是可迭代的,第二个参数是生成的元组的长度(在这种情况下,从1len(l) )。

More about combinations: http://docs.python.org/library/itertools.html#itertools.combinations关于组合的更多信息: http : //docs.python.org/library/itertools.html#itertools.combinations

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

If you want a oneliner.如果你想要一个单线。

I think it's worth boiling down the other answers here into a simple Python 3 example:我认为值得将这里的其他答案归结为一个简单的 Python 3 示例:

from itertools import chain, combinations

def all_combinations(array):
    return chain(*(list(combinations(array, i + 1)) for i in range(len(array))))

This returns an iterable, to view the values:这将返回一个可迭代的,以查看值:

>>> print(list(all_combinations((1, 2, 3))))
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM