【问题标题】:Combinations without using "itertools.combinations"不使用“itertools.combinations”的组合
【发布时间】:2013-12-24 17:53:47
【问题描述】:

我需要的是一次为两个元素创建组合。

如果列表包含:seq = ['A', 'B', 'C'] 输出将是com = [['A', 'B'], ['A', 'C'], ['B', 'C']]

这一切都没有itertools.combinations 方法。

我使用以下代码进行排列。但是我该如何修改它以使其与组合一起使用?

def permute(seq):

    if len(seq) <= 1:
        perms = [seq]
    else:
        perms = []
        for i in range(len(seq)):
            sub = permute(seq[:i]+seq[i+1:]) 
            for p in sub:    
                perms.append(seq[i:i+1]+p)

return perms

【问题讨论】:

  • 为什么没有 itertools?
  • combinations 的等效源代码在 itertools 文档页面上。只需将其复制粘贴到您的文件中即可。
  • 是的,我不能使用其他方法。谢谢,我去看看。
  • @jonrsharpe itertools.combinations 函数返回字典排序顺序,这对于整数列表可能是不可取的 - 即 combinations([1,2,10,3], 3)[1,2,3] 之前产生 [1,2,10]

标签: python combinations


【解决方案1】:

如果您不想使用itertools,请使用documented pure-Python equivalent

def combinations(iterable, r):
    # combinations('ABCD', 2) --> AB AC AD BC BD CD
    # combinations(range(4), 3) --> 012 013 023 123
    pool = tuple(iterable)
    n = len(pool)
    if r > n:
        return
    indices = range(r)
    yield tuple(pool[i] for i in indices)
    while True:
        for i in reversed(range(r)):
            if indices[i] != i + n - r:
                break
        else:
            return
        indices[i] += 1
        for j in range(i+1, r):
            indices[j] = indices[j-1] + 1
        yield tuple(pool[i] for i in indices)

【讨论】:

  • 这个的大 O 时间复杂度是多少?我认为是O(r * (n! / (r! (n - r)!)))while 循环nCr 次,tuple(pool[i] for i in indices) 使每个循环都有O(r) 工作。所以这个迭代解决方案看起来比recursive backtracking solution高效得多,我认为是O(n^r)
  • 我没有做过复杂度分析;乍一看,我认为您的复杂性是正确的。它肯定远低于 O(nr)。
  • while 循环内的 else 与哪个 if 语句相关联?我以前从未见过这种情况。
  • @c_sagan:它不与任何if 语句相关联,它与for 循环相关联。在 python 中,whilefor 也有else 块,当循环完成而不通过break 退出时执行。
  • @Gulzar: 所以,对于输入iterable=[0, 1, 2, 3], r=3,你从索引[0, 1, 2]开始,看到第三个索引可以增加所以你得到[0, 1, 3],看你不能增加第三个索引进一步移动到第二个索引得到[0, 2, 3],然后移动到第一个索引得到[1, 2, 3]。请注意这与文档字符串中记录的示例如何匹配。
【解决方案2】:

这很简单直接做:

def comb2(s):
    for i, v1 in enumerate(s):
        for j in range(i+1, len(s)):
            yield [v1, s[j]]

然后:

print list(comb2(['A', 'B', 'C']))

显示:

[['A', 'B'], ['A', 'C'], ['B', 'C']]

唯一让组合变得棘手的事情是满足一次只在运行时已知的元素数量。只要您事先知道这个数字,嵌套那么深的固定数量的循环就可以很明显地完成这项工作。

【讨论】:

    【解决方案3】:
    def combo2(lst,n):
        if n==0:
            return [[]]
        l=[]
        for i in range(0,len(lst)):
            m=lst[i]
            remLst=lst[i+1:]
            for p in combo2(remLst,n-1):
                l.append([m]+p)
        return l
    

    输入:

    combo2(list('ABC'),2)
    

    输出:

    [['A', 'B'], ['A', 'C'], ['B', 'C']]
    

    【讨论】:

      【解决方案4】:

      以下是answer 中递归 C++ 代码对类似问题的粗略翻译:

      def combinations(sequence, length, NULL=object()):
          """ Find all combinations of the specified length from a sequence. """
          if length <= 0:
              combos = [NULL]
          else:
              combos = []
              for i, item in enumerate(sequence, 1):
                  rem_items = sequence[i:]
                  rem_combos = combinations(rem_items, length-1)
                  combos.extend(item if combo is NULL else [item, combo]
                                  for combo in rem_combos)
          return combos
      
      print(combinations(['A', 'B', 'C'], 2))
      

      输出:

      [['A', 'B'], ['A', 'C'], ['B', 'C']]
      

      【讨论】:

        【解决方案5】:

        纯python中的组合

        # generate combination of two list
        import copy
        def extend_list(list1,list2):
            temp=[];temp=copy.deepcopy(list1);temp.append(list2)
            return temp
        def combination(list1, list2):
            return [extend_list(item1,item2) if type(item1) is list else [item1,item2] for item1 in list1 for item2 in list2]
        
        # generate all combination of list of variables
        def list_combination(list_of_variables):
            '''list_of_variables is a list of list e.g [[1,2],['True','False']]'''
            node_combinations=[]
            no_of_variables=len(list_of_variables)
            node_combinations=list_of_variables[0]
            for i in range(no_of_variables-1):
                node_combination = combination(node_combinations,list_of_variables[i+1])
                node_combinations=node_combination
            return node_combinations
        

        输出

        input_list = [['TRUE', 'FALSE'], [1, 2], ['TRUE', 'FALSE']]
        list_combination(input_list)
        
        [['TRUE', 1, 'TRUE'],
         ['TRUE', 1, 'FALSE'],
         ['TRUE', 2, 'TRUE'],
         ['TRUE', 2, 'FALSE'],
         ['FALSE', 1, 'TRUE'],
         ['FALSE', 1, 'FALSE'],
         ['FALSE', 2, 'TRUE'],
         ['FALSE', 2, 'FALSE']]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-01-24
          • 1970-01-01
          • 1970-01-01
          • 2020-04-06
          • 1970-01-01
          • 2013-06-30
          相关资源
          最近更新 更多