【问题标题】:Generating all possible combinations of a list, "itertools.combinations" misses some results生成列表的所有可能组合,“itertools.combinations”会遗漏一些结果
【发布时间】:2013-06-30 07:42:45
【问题描述】:

给定 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)一样
  • 好问题。虽然从技术上讲,您可以编写自己的函数来获得这些组合。

标签: python list combinations


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    您可以使用这个简单的代码在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)]
    

    【讨论】:

    • 要求在结果中查看 (2, 1) 的问题。您的答案中的 (2, 1) 在哪里?
    • 组合 (2, 1) 和 (1, 2) 都是同一个家伙。
    • 尽管问题中有“组合”,但它的意思是排列。读到最后,发现 (2, 1) 和 (1, 2) 都是 OP 所期望的。
    【解决方案3】:

    您是在寻找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) 是完全不同的。

      【讨论】:

        【解决方案5】:

        这里是没有 itertools 的解决方案

        首先让我们定义01s的指示向量与子列表(1如果项目在子列表中)之间的转换

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

        接下来,定义一个从02^n-1 之间的数字到其二进制向量表示的映射(使用字符串的format 函数):

        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)
        

        【讨论】:

          【解决方案6】:

          我假设您希望所有可能的组合都作为值的“集合”。这是我编写的一段代码,可能有助于您了解一下:

          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!时间复杂度,所以要小心。这可行,但可能不是最有效的

          【讨论】:

            【解决方案7】:

            我只是想把它放在那里,因为我无法对每一个可能的结果都进行优化,并且请记住,当涉及到 python 时,我只有最原始的最基本知识,并且可能有一个更优雅的解决方案...... (也请原谅可怜的变量名

            测试 = [1, 2, 3]

            测试2= [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 因为我正在使用整数,但您可能需要相应地修改它...

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-01-07
              相关资源
              最近更新 更多