问题描述
我正在尝试将单个 for 循环分成多个循环。我能够将单个循环变成两个循环,如下所示:
console.config({
maxEntries: Infinity
});
// looping 0-100
let q = 100;
for (let i of [...Array(q % 10 === 0 ? q / 10 : (q - q % 10) / 10 + 1).keys()]) {
for (let j of [...Array(((i + 1) * 10 <= q ? 10 : q % 10)).keys()]) {
console.log(i * 10 + j);
}
}
.as-console-wrapper {
max-height: 100% !important;
}
(我知道它看起来不太漂亮)
我想将同一个循环变成 3 或 4 个循环。我该怎么做?
解决方法
不是按 1 迭代 i
和 j
,而是按行大小迭代 i
并从 j
开始 i
。
let q = 25;
let rowsize = 10;
for (let i = 0; i < q; i += rowsize) {
for (let j = i; j < Math.min(i + rowsize,q); j++) {
console.log(j);
}
}
.as-console-wrapper {
max-height: 100% !important;
}
如果您想将具有 n 次迭代的循环拆分为多个嵌套循环,您需要找到其乘积为 n 的多个值。喜欢
100 = 10*10
100 = 10*5*2
//up to
100 = 5*5*2*2
以及这些的所有组合,例如 5*5*4
或 25*4
或 25*2*2
...
所以第一步是找到你想要的迭代次数的主要因素,看看你的选择是什么。
function* primes(limit) {
yield 2;
var i = 3,sieve = new Int32Array(Math.ceil(limit / 64)).fill(-1);
for (; i * i <= limit; i += 2)
if (sieve[i >> 6] & (1 << (i >> 1 & 31))) {
yield i;
for (var j = i * i; j <= limit; j += i + i)
sieve[j >> 6] &= ~(1 << (j >> 1 & 31));
}
for (; i <= limit; i += 2)
if (sieve[i >> 6] & (1 << (i >> 1 & 31)))
yield i;
}
const iterations = document.querySelector("#iterations");
const factors = document.querySelector("#factors");
(iterations.oninput = function() {
let v = iterations.valueAsNumber;
if (isNaN(v)) return;
let factors = [];
for (let prime of primes(v)) {
if (prime * prime > v) break;
while (v % prime === 0) {
factors.push(prime);
v /= prime;
}
}
if (v > 1 || factors.length === 0) factors.push(v);
document.querySelector("#iterations-out").textContent = factors.join(" * ");
})();
(factors.oninput = function() {
const numbers = document.querySelector("#factors").value.match(/\d+/g);
if (!numbers) return;
let pre = " ".repeat(numbers.length) + "console.log(";
let post = "0);";
const iterations = numbers.reduceRight((factor,v,i) => {
const padding = " ".repeat(i);
const w = String.fromCharCode(97 + i);
pre = `${padding}for (let ${w} = 0; ${w} < ${v}; ++${w}) {\n${pre}`;
post = `${w} * ${factor} + ${post}\n${padding}}`;
return factor * v;
},1);
document.querySelector("#factors-out").textContent = `// total = ${iterations}\n${pre}${post}`.replace(" * 1 + 0","");
})();
<label>numbers to factors: <input id="iterations" value="100" type="number" /></label>
<pre id="iterations-out"></pre>
<label>factors to loops: <input id="factors" value="10 10" /></label>
<em>(somehow sepetrated numbers)</em>
<pre id="factors-out"></pre>
问题在于,如果您的迭代次数为质数或由(太大)质因数组成。
由于我对 MongoDB 聚合框架以及您正在构建的内容知之甚少,因此我只能建议将一个循环(嵌套与否)替换为两个或多个包含更好因子的连续循环。
像 127
-> prime 不能被精确分割,但 63
(3*3*7)
+ 64 (2*2*2*2*2*2)
效果更好。
for (let a = 0; a < 9; ++a) {
for (let b = 0; b < 7; ++b) {
console.log(a * 7 + b);
}
}
// offset = 63;
for (let a = 0; a < 8; ++a) {
for (let b = 0; b < 8; ++b) {
console.log(a * 8 + b + 63);
}
}
// total 127 iterations