当前位置:  开发笔记 > 编程语言 > 正文

如何获得列表元素的所有可能组合?

如何解决《如何获得列表元素的所有可能组合?》经验,为你挑选了11个好方法。

我有一个包含15个数字的列表,我需要编写一些代码来生成这些数字的所有32,768种组合.

我发现了一些代码(通过谷歌搜索)显然正在寻找我正在寻找的东西,但我发现代码相当不透明并且对使用它很谨慎.另外我觉得必须有一个更优雅的解决方案.

我发生的唯一事情就是循环遍历十进制整数1-32768并将它们转换为二进制,并使用二进制表示作为过滤器来选择适当的数字.

有谁知道更好的方法?使用map(),也许?



1> Dan H..:

这个答案错过了一个方面:OP要求所有组合...而不仅仅是长度"r"的组合.

所以你要么必须遍历所有长度"L":

import itertools

stuff = [1, 2, 3]
for L in range(0, len(stuff)+1):
    for subset in itertools.combinations(stuff, L):
        print(subset)

或者 - 如果你想变得时髦(或者在你之后读取你的代码的大脑弯曲) - 你可以生成"combination()"生成器链,并迭代:

from itertools import chain, combinations
def all_subsets(ss):
    return chain(*map(lambda x: combinations(ss, x), range(0, len(ss)+1)))

for subset in all_subsets(stuff):
    print(subset)


感谢您的支持!在我发布上述回复后的几周内,我发现Ben正在寻找的概念的名称是原始15件物品的"powerset".实际上,在标准的python"itertools"文档页面上给出了一个示例实现:http://docs.python.org/library/itertools.html(grep for"powerset").
对于读到这里的人来说:[`itertools`文档]的食谱部分中的**`powerset()`**生成器函数(https://docs.python.org/2/library/itertools.html#recipes )更简单,可能使用更少的内存,并且可能比这里显示的实现更快.

2> James Brady..:

看看itertools.combinations:

itertools.combinations(iterable, r)

返回输入iterable中元素的r个子序列.

组合以字典排序顺序发出.因此,如果对输入iterable进行排序,则将按排序顺序生成组合元组.

从2.6开始,包括电池!


你可以列出一切.`list(itertools.combinations(iterable,r))`

3> ninjagecko..:

这是一个懒惰的单行,也使用itertools:

from itertools import compress, product

def combinations(items):
    return ( set(compress(items,mask)) for mask in product(*[[0,1]]*len(items)) )
    # alternative:                      ...in product([0,1], repeat=len(items)) )

这个答案背后的主要思想是:有2 ^ N个组合 - 与长度为N的二进制字符串的数量相同.对于每个二进制字符串,您选择对应于"1"的所有元素.

items=abc * mask=###
 |
 V
000 -> 
001 ->   c
010 ->  b
011 ->  bc
100 -> a
101 -> a c
110 -> ab
111 -> abc

需要考虑的事项:

这就需要你可以调用len(...)items(解决方法:如果items是像就像一台发电机的迭代,用第一把它变成一个列表items=list(_itemsArg))

这要求迭代的顺序items不是随机的(解决方法:不要疯狂)

这就要求项目是独一无二的,要不然{2,2,1}{2,1,1}都将崩溃{2,1}(解决方法:使用collections.Counter作为一个下拉更换set;它基本上是一个多集...尽管你可能需要在以后使用tuple(sorted(Counter(...).elements())),如果你需要它是可哈希)


演示

>>> list(combinations(range(4)))
[set(), {3}, {2}, {2, 3}, {1}, {1, 3}, {1, 2}, {1, 2, 3}, {0}, {0, 3}, {0, 2}, {0, 2, 3}, {0, 1}, {0, 1, 3}, {0, 1, 2}, {0, 1, 2, 3}]

>>> list(combinations('abcd'))
[set(), {'d'}, {'c'}, {'c', 'd'}, {'b'}, {'b', 'd'}, {'c', 'b'}, {'c', 'b', 'd'}, {'a'}, {'a', 'd'}, {'a', 'c'}, {'a', 'c', 'd'}, {'a', 'b'}, {'a', 'b', 'd'}, {'a', 'c', 'b'}, {'a', 'c', 'b', 'd'}]



4> martineau..:

在@Dan H 高度评价的回答中的评论中,提到powerset()itertools文档中的配方- 包括Dan本人的一个.但是,到目前为止还没有人发布它作为答案.因为这可能是解决问题的最好方法之一 - 并且考虑到另一位评论者的一点鼓励,如下所示.该函数生成每个可能长度的列表元素的所有唯一组合(包括那些包含零和所有元素的组合).

注意:如果,微妙的不同,目标是获得独特元素的唯一组合,改线s = list(iterable),以s = list(set(iterable))消除任何重复的元素.无论如何,这iterable最终变成了一种list手段,它将与发电机一起工作(与其他几个答案不同).

from itertools import chain, combinations

def powerset(iterable):
    "powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"
    s = list(iterable)  # allows duplicate elements
    return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))

stuff = [1, 2, 3]
for i, combo in enumerate(powerset(stuff), 1):
    print('combo #{}: {}'.format(i, combo))

输出:

combo #1: ()
combo #2: (1,)
combo #3: (2,)
combo #4: (3,)
combo #5: (1, 2)
combo #6: (1, 3)
combo #7: (2, 3)
combo #8: (1, 2, 3)



5> darxtrix..:

这是一个使用递归:

>>> import copy
>>> def combinations(target,data):
...     for i in range(len(data)):
...         new_target = copy.copy(target)
...         new_data = copy.copy(data)
...         new_target.append(data[i])
...         new_data = data[i+1:]
...         print new_target
...         combinations(new_target,
...                      new_data)
...                      
... 
>>> target = []
>>> data = ['a','b','c','d']
>>> 
>>> combinations(target,data)
['a']
['a', 'b']
['a', 'b', 'c']
['a', 'b', 'c', 'd']
['a', 'b', 'd']
['a', 'c']
['a', 'c', 'd']
['a', 'd']
['b']
['b', 'c']
['b', 'c', 'd']
['b', 'd']
['c']
['c', 'd']
['d']



6> Mathieu Rodi..:

这个单行程序为您提供所有组合(如果原始列表/集合包含不同的元素之间的项目0n项目n)并使用本机方法itertools.combinations:

Python 2

from itertools import combinations

input = ['a', 'b', 'c', 'd']

output = sum([map(list, combinations(input, i)) for i in range(len(input) + 1)], [])

Python 3

from itertools import combinations

input = ['a', 'b', 'c', 'd']

output = sum([list(map(list, combinations(input, i))) for i in range(len(input) + 1)], [])

输出将是:

[[],
 ['a'],
 ['b'],
 ['c'],
 ['d'],
 ['a', 'b'],
 ['a', 'c'],
 ['a', 'd'],
 ['b', 'c'],
 ['b', 'd'],
 ['c', 'd'],
 ['a', 'b', 'c'],
 ['a', 'b', 'd'],
 ['a', 'c', 'd'],
 ['b', 'c', 'd'],
 ['a', 'b', 'c', 'd']]

在线试用:

http://ideone.com/COghfX


@AdHominem:不,不是.这是所有组合的列表.排列将包括,例如`['b','a']`.

7> HongboZhu..:

我同意Dan H的观点,Ben确实要求所有组合.itertools.combinations()没有给出所有组合.

另一个问题是,如果输入可迭代很大,那么返回生成器而不是列表中的所有内容可能更好:

iterable = range(10)
for s in xrange(len(iterable)+1):
  for comb in itertools.combinations(iterable, s):
    yield comb



8> saimadhu.pol..:

您可以使用这个简单的代码在python中生成列表的所有组合

import itertools

a = [1,2,3,4]
for i in xrange(0,len(a)+1):
   print list(itertools.combinations(a,i))

结果将是:

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



9> 小智..:

我想我会为那些寻求答案的人添加这个功能,而无需导入itertools或任何其他额外的库.

def powerSet(items):
    """
    Power set generator: get all possible combinations of a list’s elements

    Input:
        items is a list
    Output:
        returns 2**n combination lists one at a time using a generator 

    Reference: edx.org 6.00.2x Lecture 2 - Decision Trees and dynamic programming
    """

    N = len(items)
    # enumerate the 2**N possible combinations
    for i in range(2**N):
        combo = []
        for j in range(N):
            # test bit jth of integer i
            if (i >> j) % 2 == 1:
                combo.append(items[j])
        yield combo

简单的Yield Yield用法:

for i in powerSet([1,2,3,4]):
    print (i, ", ",  end="")

以上用法示例的输出:

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



10> Jonathan R..:

这种方法可以轻松地转移到所有支持递归的编程语言中(无itertools,无收益,无列表理解)

def combs(a):
    if len(a) == 0:
        return [[]]
    cs = []
    for c in combs(a[1:]):
        cs += [c, c+[a[0]]]
    return cs

>>> combs([1,2,3,4,5])
[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], ..., [5, 4, 3, 2, 1]]



11> ninjagecko..:

这是另一个解决方案(单线程),涉及使用itertools.combinations函数,但在这里我们使用双列表理解(而不是for循环或求和):

def combs(x):
    return [c for i in range(len(x)+1) for c in combinations(x,i)]

演示:

>>> combs([1,2,3,4])
[(), 
 (1,), (2,), (3,), (4,), 
 (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), 
 (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), 
 (1, 2, 3, 4)]

推荐阅读
TXCWB_523
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有