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)
递归在这里是过度的.更快的解决方案:
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)