生成列表的所有可能组合,“itertools.combinations”会漏掉一些结果。

31

在Python中给定一个项目列表,如何获取所有可能的项目组合?

这个网站上有几个类似的问题建议使用itertools.combinations,但是它只返回我需要的子集:

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

()
(1,)
(2,)
(3,)
(1, 2)
(1, 3)
(2, 3)
(1, 2, 3)

正如你所看到的,它只以严格的顺序返回项目,不会返回 (2, 1), (3, 2), (3, 1), (2, 1, 3), (3, 1, 2), (2, 3, 1), 和 (3, 2, 1)。有没有什么方法可以解决这个问题?我好像想不出来。


组合中顺序无关紧要,(2, 1) 和 (1, 2) 是相同的。 - Hunter McMillen
好问题。虽然从技术上讲,你可以编写自己的函数来获取这些组合。 - Sam
7个回答

40

使用itertools.permutations

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

关于 itertools.permutations 的帮助:

permutations(iterable[, r]) --> permutations object

Return successive r-length permutations of elements in the iterable.

permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)

12

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

import itertools

a = [1,2,3,4]
for i in xrange(1,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)]

4
问题要求在结果中看到(2,1)。你的答案中(2,1)在哪里? - P_Rein
5
组合(2,1)和(1,2)是相同的组合。 - saimadhu.polamuri
2
尽管问题中提到了“组合”,但实际上指的是排列。请仔细阅读直到最后,看到原帖期望得到(2,1)和(1,2)两个结果。 - P_Rein

8

您是否正在寻找itertools.permutations

根据help(itertools.permutations)

Help on class permutations in module itertools:

class permutations(__builtin__.object)
 |  permutations(iterable[, r]) --> permutations object
 |  
 |  Return successive r-length permutations of elements in the iterable.
 |  
 |  permutations(range(3), 2) --> (0,1), (0,2), (1,0), (1,2), (2,0), (2,1)

示例代码:

>>> from itertools import permutations
>>> stuff = [1, 2, 3]
>>> for i in range(0, len(stuff)+1):
        for subset in permutations(stuff, i):
               print(subset)


()
(1,)
(2,)
(3,)
(1, 2)
(1, 3)
(2, 1)
(2, 3)
(3, 1)
(3, 2)
(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)

来自维基百科,排列与组合的区别:

排列:

非正式地说,一组对象的排列是将这些对象按照特定顺序排列。例如,集合 {1,2,3} 有六种排列方式,分别为 (1,2,3), (1,3,2), (2,1,3), (2,3,1), (3,1,2) 和 (3,2,1)。

组合:

在数学中,组合是从一个较大的群体中选择若干个物品的方式,与排列不同的是,组合中物品的顺序无关紧要。


4

itertools.permutations 是您想要的内容。根据数学定义,对于 combinations,顺序并不重要,这意味着 (1,2) 被认为与 (2,1) 相同。而对于 permutations,每个不同的排序都被视为唯一的排列,因此 (1,2)(2,1) 是完全不同的。


4

这是一个没有使用itertools的解决方案

首先,让我们定义一个指示向量和子列表之间的转换(如果项目在子列表中,则为1

def indicators2sublist(indicators,arr):
   return [item for item,indicator in zip(arr,indicators) if int(indicator)==1]

下一步,我们将定义一个从0到2^n-1的数字到其二进制向量表示的映射(使用字符串的格式化函数):
def bin(n,sz):
   return ('{d:0'+str(sz)+'b}').format(d=n)

我们所要做的就是迭代所有可能的数字,并调用indicators2sublist
def all_sublists(arr):
  sz=len(arr)
  for n in xrange(0,2**sz):
     b=bin(n,sz)
     yield indicators2sublist(b,arr)

0

我猜你想要所有可能的组合作为值的“集合”。这里是我写的一段代码,可以帮助你有一个思路:

def getAllCombinations(object_list):
    uniq_objs = set(object_list)
    combinations = []
    for obj in uniq_objs:
        for i in range(0,len(combinations)):
            combinations.append(combinations[i].union([obj]))
        combinations.append(set([obj]))
return combinations

这里是一个示例:

combinations = getAllCombinations([20,10,30])
combinations.sort(key = lambda s: len(s))
print combinations
... [set([10]), set([20]), set([30]), set([10, 20]), set([10, 30]), set([20, 30]), set([10, 20, 30])]

我认为这个算法的时间复杂度是n!,所以要小心谨慎。虽然可以使用,但可能并不是最高效的方法。


-2

我想提出这个问题,因为我找不到每种可能的结果,并且要记住,当涉及到Python时,我只有最基本的知识,可能有更优雅的解决方案...(还请原谅糟糕的变量名称

testing = [1, 2, 3]

testing2= [0]

n = -1

def testingSomethingElse(number):

try:

    testing2[0:len(testing2)] == testing[0]

    n = -1

    testing2[number] += 1

except IndexError:

    testing2.append(testing[0])

当真:

n += 1

testing2[0] = testing[n]

print(testing2)

if testing2[0] == testing[-1]:

    try:

        n = -1

        testing2[1] += 1

    except IndexError:

        testing2.append(testing[0])

    for i in range(len(testing2)):

        if testing2[i] == 4:

            testingSomethingElse(i+1)

            testing2[i] = testing[0]

我使用 == 4 是因为我在处理整数,但你可能需要相应地进行修改...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接