zoukankan      html  css  js  c++  java
  • python 多层for循环转递归/迭代

    使用场景

    枚举组合:

    问题是这样的.

    有 n 个列表,分别从每个列表中取出一个元素,一共有多少种组合?

    例如:

    a = ['a1','a2']
    b = ['b1','b2','b3']
    

    组合结果为:

    [
      ('a1','b1'),
      ('a1','b2'),
      ('a1','b3'),
      ('a2','b1'),
      ('a2','b2'),
      ('a2','b3')
    ]
    

    待组合的列表只有两个

    这种情况就是简单的遍历:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流群:778463939
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    a = ['a1','a2']
    b = ['b1','b2','b3']
    
    res = []
    for i in a:
      for j in b:
        res.append((i,j)])
    
    print(res)
    

    扩展为 n 个

    如果还用for循环嵌套,代码就是这样的

    a = ['a1','a2']
    b = ['b1','b2','b3']
    
    res = []
    for i in a:
      for j in b:
        for k in c:
            ...
               ...
    

    如果是n层的话,这样的代码是无法表达的.

    我们可以先将第一个和第二个组合,再拿组合出的结果和第三个组合,依次类推...

    如下如所示:
    在这里插入图片描述
    用代码表示如下:

    迭代

    def merge(i,j):
      """
      i = "a"
      j = ("b","c")
      return: ("a","b","c")
      """
      res = []
      for p in (i,j):
        if isinstance(p,tuple):
          res.extend(p)
        else:
          res.append(p)
      return tuple(res)
    
    def combineN(*args):
      target = args[0]
      for li in args[1:]:
        tmp = []
        for i in target:
          for j in li:
            tmp.append(merge(i,j))
        target = tmp
      return target
    

    递归

    def merge(i,j):
      """
      i = "a"
      j = ("b","c")
      return: ("a","b","c")
      """
      res = []
      for p in (i,j):
        if isinstance(p,tuple):
          res.extend(p)
        else:
          res.append(p)
      return tuple(res)
    
    def combine2(a, b):
        res = []
        for i in a:
            for j in b:
                res.append(merge(i,j))
        return res
    
    def combineNRecursion(*args):
      if len(args) == 2:
        return combine2(*args)
    
      return combine2(args[0],combineNRecursion(*args[1:]))
    

    通用的多层 for 循环转迭代

    上面用到的迭代方法是针对具体问题分析得来的,那么有没有一种通用的转换方案呢? 答案是肯定的.

    def combineN(*li):
        res = []
        # 相当于最内层循环执行的次数.
        total_times = reduce(lambda x, y: x*y, [len(item) for item in li])
        n = 0
        while n < total_times:
            tmp = n
            tem_res = []
            for i in range(len(li)):
                # 余数就是参与计算的元素的下标,商用于计算下一个列表参与元素的下标.
                tmp, cur = divmod(tmp, len(li[i]))
                tem_res.append(li[i][cur])
            res.append(tem_res)
            n += 1
        return res
    
    res = combineN(["a1","a2"], ["b1", "b2"], ["c1", "c2"])
    for i in res:
        print(i)
    

    输出结果如下:

    ['a1', 'b1', 'c1']
    ['a2', 'b1', 'c1']
    ['a1', 'b2', 'c1']
    ['a2', 'b2', 'c1']
    ['a1', 'b1', 'c2']
    ['a2', 'b1', 'c2']
    ['a1', 'b2', 'c2']
    ['a2', 'b2', 'c2']
    
  • 相关阅读:
    Java学习开篇
    《我的姐姐》
    世上本无事,庸人自扰之
    这48小时
    补觉
    淡定
    es java api 设置index mapping 报错 mapping source must be pairs of fieldnames and properties definition.
    java mongodb groupby分组查询
    linux 常用命令
    mongodb too many users are authenticated
  • 原文地址:https://www.cnblogs.com/xxpythonxx/p/13708740.html
Copyright © 2011-2022 走看看