【问题标题】:How to create variable dual for loops? [duplicate]如何创建变量对偶for循环? [复制]
【发布时间】:2022-01-05 01:58:09
【问题描述】:

我想创建一个函数,其行为方式与下面的 for 循环相同,具体取决于变量 n:

function(n, max_anz, max_size_ , step)

n = 1

z = 0
for a1 in range(max_anz + 1):
    for x1 in range(0, max_size, step):
        
        print([a1, x1])
        z += 1
print(z)

n = 2

z = 0
for a1 in range(max_anz + 1):
    for x1 in range(0, max_size, step):
        
        for a2 in range(max_anz + 1):
            for x2 in range(0, max_size, step):
                
                print([a1, x1, a2, x2])
                z = z+1
print(z)

n = 3

z = 0
for a1 in range(max_anz + 1):
    for x1 in range(0, max_size, step):
        
        for a2 in range(max_anz + 1):
            for x2 in range(0, max_size, step):
                
                for a3 in range(max_anz + 1):
                    for x3 in range(0, max_size, step):
                
                        print([a1, x1, a2, x2, a3, x3])
                        z = z+1

打印(z)

【问题讨论】:

标签: python for-loop variables recursion


【解决方案1】:

使用带有“重复”参数的 itertools.product。

import itertools as it

def function(n, max_anz, max_size, step):
    lst = [list(e) for e in it.product(range(max_anz+1), range(0, max_size, step), repeat = n)]
    print(*lst, sep='\n')
    print(len(lst))

或者使用生成器来防止构建完整列表:

def function(n, max_anz, max_size, step):
    g = it.product(range(max_anz+1), range(0, max_size, step), repeat = n)
    
    i = 0
    for e in g:
        i += 1
        print(list(e))
    print(i)

可以缩短:

def function(n, max_anz, max_size, step):
    i = 0
    for e it.product(range(max_anz+1), range(0, max_size, step), repeat = n):
        i += 1
        print(list(e))
    print(i)

【讨论】:

  • 我建议在 for 循环之前添加 i = -1。否则,您可能会尝试在根本没有定义 i 的情况下打印 i+1 。例如,function(1, 1, 0, 1) 当前引发异常UnboundLocalError: local variable 'i' referenced before assignment。一般来说,我对在循环外引用循环变量有非常强烈的厌恶。如果你想计算迭代次数,你可以明确地这样做:number_of_iterations=0; for e in it.product(...): print(list(e)); number_of_iterations += 1; print(number_of_iterations)
  • @Stef,我根据您的建议编辑了答案。随意编辑。
【解决方案2】:

您可以使用递归来做您想做的事情,使用一个函数调用自己,使用n-1(如果n 大于一)并传递一些部分结果以进行构建。

下面的 sn-p 演示了这种方法来解决一个更简单的问题,在 n 的每个级别上只有一个 for 循环。

def make_list(n, limit, context=None):
    z = 0
    for val in range(limit):
        new_list = [] if context is None \
            else context.copy()
        new_list.append(val)
        if n > 1:
            z += make_list(n-1, limit, context=new_list)
        else:
            print(new_list)
            z += 1
    return z

make_list(2, 3)
# [0, 0]
# [0, 1]
# [0, 2]
# [1, 0]
# [1, 1]
# [1, 2]
# [2, 0]
# [2, 1]
# [2, 2]
# Out[10]: 9

【讨论】:

    【解决方案3】:

    itertools.product 是 Python 中解决此问题的首选解决方案,但作为程序员,您不应该坐等功能出现在您选择的语言或库中。例如,如果你要把这个问题交给 JavaScript,你会怎么做?

    您注意到一个模式,因此将其包装在一个函数中并定义必要的参数。使用简单的inductive reasoning 我们可以构造函数 -

    1. 如果n 小于或等于零,则不再循环,产生空结果
    2. (感应)n 为 1 或更大。运行你的循环,对于子问题n-1 的每个结果r,在ax 前面加上结果
    def myfunc(n, max_anz, max_size, step):
      if n <= 0:
        yield ()                                   #1
      else:
        for a in range(max_anz + 1):               #2
          for x in range(0, max_size, step):
            for r in myfunc(n - 1, max_anz, max_size, step):
              yield (a, x, *r)
    

    现在您可以使用您的参数调用myfunc -

    for r in myfunc(2, 3, 4, 1):
      print(r)
    
    (0, 0, 0, 0)
    (0, 0, 0, 1)
    (0, 0, 0, 2)
    ...
    (3, 3, 3, 1)
    (3, 3, 3, 2)
    (3, 3, 3, 3)
    

    如果愿意,您可以在list 中收集所有组合,其中len 为您提供组合的总数(您的问题中为z)-

    result = list(myfunc(2, 3, 4, 1))
    print(result)
    print(len(result))
    
    [
      (0, 0, 0, 0),
      (0, 0, 0, 1),
      (0, 0, 0, 2),
      ...,
      (3, 3, 3, 1),
      (3, 3, 3, 2),
      (3, 3, 3, 3)
    ]
    256
    

    【讨论】:

      猜你喜欢
      • 2019-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多