3

Python:

当要循环的索引数量是动态的时,如何高效地执行多维循环。

假设一个数组 var_size 包含每个变量的大小

var_size = [ 3, 4, 5 ]

和一个函数'loop',它将为每个点调用'f(current_state)'。

  def f(state): print state
  loop(var_size, f)

此调用将按以下顺序调用f :

 f( [ 0, 0, 0])
 f( [ 0, 0, 1])
 f( [ 0, 0, 2])
 f( [ 0, 1, 0])
 etc....
4

3 回答 3

4

你可以这样做itertools.product

>>> print list(itertools.product(*(range(x) for x in reversed([3,4,5]))))
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 2, 0), (0, 2, 1), (0, 2, 2), (0, 3, 0), (0, 3, 1), (0, 3, 2), (1, 0, 0), (1, 0, 1), (1, 0, 2), (1, 1, 0), (1, 1, 1), (1, 1, 2), (1, 2, 0), (1, 2, 1), (1, 2, 2), (1, 3, 0), (1, 3, 1), (1, 3, 2), (2, 0, 0), (2, 0, 1), (2, 0, 2), (2, 1, 0), (2, 1, 1), (2, 1, 2), (2, 2, 0), (2, 2, 1), (2, 2, 2), (2, 3, 0), (2, 3, 1), (2, 3, 2), (3, 0, 0), (3, 0, 1), (3, 0, 2), (3, 1, 0), (3, 1, 1), (3, 1, 2), (3, 2, 0), (3, 2, 1), (3, 2, 2), (3, 3, 0), (3, 3, 1), (3, 3, 2), (4, 0, 0), (4, 0, 1), (4, 0, 2), (4, 1, 0), (4, 1, 1), (4, 1, 2), (4, 2, 0), (4, 2, 1), (4, 2, 2), (4, 3, 0), (4, 3, 1), (4, 3, 2)]

请注意,我生成的是tuples 而不是lists,但如果您确实需要,这很容易解决。

所以,在我看来,你想要:

map(f,itertools.product(*map(range,reversed(var_size))))
于 2013-04-17T00:01:14.800 回答
0

这段代码完成了这项工作 - 它的优点是不创建列表。然而,它并不那么优雅......

关于如何变得更好的任何想法?

def loop(var_size, f):
    nb = len(var_size)
    state = [0]*nb
    ok = True
    while ok:
        f(state)
        for i in range(nb-1, -1, -1):
            state[i] = state[i]+1
            if state[i] < var_size[i]:
                break
            else:
                if i == 0:
                    ok = False
                    break
                else:
                    state[i] = 0

var_size = [3,4,5]  
def f(state): 
    print state

loop(var_size, f)
于 2013-04-17T05:02:54.003 回答
0

使列表初始化为 0,与 var_size 中的条目一样多。我们将此列表视为“不倒翁”列表 - 我们递增列表中的最后一个,直到它超出其限制(又名 var_size 在列表中的同一点)。如果是这样,我们将其设置为 0,向左移动并重复增量/溢出检查,直到我们不溢出(将“我们正在查看的 tumbler”变量重置回最后一个并继续)或溢出所有条目list (我们完成了,我们一直循环),然后执行下一个调用。

我不知道这是最优的还是 pythonic 的,但它是 O(n)。

于 2013-04-16T23:37:56.813 回答