可变数量的嵌套for循环

pim*_*vdb 23 javascript combinatorics nested-loops

编辑:对不起,但我忘了提到我需要计数器变量的值.所以制作一个循环并不是我害怕的解决方案.

我不确定这是否可行,但我想做以下事情.对于函数,传递数字数组.每个数字都是for循环的上限,例如,如果数组是[2, 3, 5],则应执行以下代码:

for(var a = 0; a < 2; a++) {
     for(var b = 0; b < 3; b++) {
          for(var c = 0; c < 5; c++) {
                doSomething([a, b, c]);
          }
     }
}
Run Code Online (Sandbox Code Playgroud)

因此,嵌套for循环的数量等于数组的长度.有没有办法让这项工作?我正在考虑创建一段代码,将每个for循环添加到一个字符串,然后通过它进行评估eval.然而,我已经阅读过,这eval不应该是一个人的首选,因为它也会产生危险的结果.

这里适合哪种技术?

Sea*_*ean 19

递归可以很好地解决这个问题:

function callManyTimes(maxIndices, func) {
    doCallManyTimes(maxIndices, func, [], 0);
}

function doCallManyTimes(maxIndices, func, args, index) {
    if (maxIndices.length == 0) {
        func(args);
    } else {
        var rest = maxIndices.slice(1);
        for (args[index] = 0; args[index] < maxIndices[0]; ++args[index]) {
            doCallManyTimes(rest, func, args, index + 1);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

像这样称呼它:

callManyTimes([2,3,5], doSomething);
Run Code Online (Sandbox Code Playgroud)


Mik*_*uel 9

递归在这里是过度的.更快的解决方案:

function allPossibleCombinations(lengths, fn) {
  var n = lengths.length;

  var indices = [];
  for (var i = n; --i >= 0;) {
    if (lengths[i] === 0) { return; }
    if (lengths[i] !== (lengths[i] & 0x7ffffffff)) { throw new Error(); }
    indices[i] = 0;
  }

  while (true) {
    fn.apply(null, indices);
    // Increment indices.
    ++indices[n - 1];
    for (var j = n; --j >= 0 && indices[j] === lengths[j];) {
      if (j === 0) { return; }
      indices[j] = 0;
      ++indices[j - 1];
    }
  }
}

allPossibleCombinations([3, 2, 2], function(a, b, c) { console.log(a + ',' + b + ',' + c); })
Run Code Online (Sandbox Code Playgroud)