如何避免选择嵌套的For循环?

时间:2020-01-24 06:49:29

标签: algorithm for-loop search combinations

例如,有 M个属性 a_1,...,a_M 可供选择,并且每个属性具有N个选择
问题是搜索N ^ M个选择的整个组合。
使用嵌套的for循环,伪代码如下所示。

# length of a_1, ..., a_M is N for each.
for c_1 in a_1:
  for c_2 in a_2:
    ...
      for c_M in a_M:
         evaluate(c_1, c_2, ..., c_M)

但是,这种极端嵌套的for循环看起来很差,我不想写M遍for语句。
另外,如果我们不知道要考虑的属性数量,我们甚至无法使用此代码。
还有其他更简单,更优雅的方法吗?

1 个答案:

答案 0 :(得分:1)

您的问题似乎与笛卡尔积有关。请注意,结果大小(组合数)为L1*L2*L3..*LM,其中Liai的选择数

您可以使用递归来实现它,或者使用适当的库(如果有)

Python示例:

import itertools
l = [['a', 'b'], [1, 2, 3], [False, True]]
print([list(a) for a in itertools.product(*l)])

>>> [['a', 1, False], ['a', 1, True], ['a', 2, False], ['a', 2, True], 
     ['a', 3, False], ['a', 3, True], ['b', 1, False], ['b', 1, True], 
     ['b', 2, False], ['b', 2, True], ['b', 3, False], ['b', 3, True]]

递归和迭代实现的示例:

def product_rec(a, fromindex, res):
    if fromindex == len(a):
        print(res)
        return
    for x in a[fromindex]:
        product_rec(a, fromindex+1, res+[x])

def product_iter(a):
    NN = 1
    for x in a:
        NN *=  len(x)  #number of combinations
    b = [[0]*len(a) for i in range(NN)]
    N = NN
    M = 1
    for k in range(len(a)):  
        N //=  len(a[k])
        c = 0
        for l in range(M):
            for i in range(len(a[k])):
                for j in range(N):
                    b[c][k] = a[k][i]
                    c += 1
        M *= len(a[k])
    print(b)

l = [['a', 'b'], [1, 2, 3], [False, True]]

product_rec(l, 0, [])
product_iter(l)