编辑:对不起,我忘了说我需要计数器变量的值。所以只做一个循环恐怕不是一个好的解决方案。
我不确定这是否可能,但我想做以下事情。传递给函数的是一个数字数组。每个数字都是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]);
}
}
}
因此,嵌套的for循环的数量等于数组的长度。有没有什么办法让这件事变得可行呢?我在考虑创建一段代码,将每个for循环添加到一个字符串中,然后通过eval
对其求值。然而,我读到过eval
不应该是人们的第一选择,因为它也可能产生危险的结果。
什么技术在这里可能是合适的?
发布于 2011-01-14 02:29:06
递归可以很好地解决这个问题:
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);
}
}
}
这样叫它:
callManyTimes([2,3,5], doSomething);
发布于 2011-01-15 02:14:31
在这里,递归被夸大了。您可以使用生成器:
function* allPossibleCombinations(lengths) {
const n = lengths.length;
let indices = [];
for (let i = n; --i >= 0;) {
if (lengths[i] === 0) { return; }
if (lengths[i] !== (lengths[i] & 0x7fffffff)) { throw new Error(); }
indices[i] = 0;
}
while (true) {
yield indices;
// Increment indices.
++indices[n - 1];
for (let j = n; --j >= 0 && indices[j] === lengths[j];) {
if (j === 0) { return; }
indices[j] = 0;
++indices[j - 1];
}
}
}
for ([a, b, c] of allPossibleCombinations([3, 2, 2])) {
console.log(`${a}, ${b}, ${c}`);
}
这里的直觉是,我们保留了一个索引列表,这些索引总是小于相应的长度。
第二个循环句柄为进位。当递增十进制数199时,我们转到(1,9,10),然后进位到get (1,10,0),最后是(2,0,0)。如果我们没有足够的位数进位,我们就完蛋了。
发布于 2011-01-14 02:14:26
设置与limit数组长度相同的计数器数组。使用单个循环,并在每次迭代中递增最后一项。当它达到它的极限时,你重新启动它并递增下一项。
function loop(limits) {
var cnt = new Array(limits.length);
for (var i = 0; i < cnt.length; i++) cnt[i] = 0;
var pos;
do {
doSomething(cnt);
pos = cnt.length - 1;
cnt[pos]++;
while (pos >= 0 && cnt[pos] >= limits[pos]) {
cnt[pos] = 0;
pos--;
if (pos >= 0) cnt[pos]++;
}
} while (pos >= 0);
}
https://stackoverflow.com/questions/4683539
复制相似问题