有没有办法制作"for loop of for loops"?
Is there a way to make a "for loop of for loops"?
我正在尝试为自己编写一个扑克计算器,我有一个 5 级深的 for 循环。
为此,我一个接一个地嵌套了 for 循环。我正在寻找一种方法来简单地使用一个循环(或函数),它可以告诉我想去多少层。对于这个例子,答案是 5,但对于其他例子,它可能是一个更高(更高)的数字,这会很麻烦。我认为递归是一种实现它的方法我只是不知道如何设置它(不太了解递归)。非常感谢您的帮助。
for(var i=0; i < deck.length; i++){
for(var j=i+1; j<deck.length; j++){
for(var k=j+1; k<deck.length;k++){
for(var m=k+1; m<deck.length;m++){
for(var n=m+1; n<deck.length;n++){
combo = deck[i];
combo += deck[j];
combo += deck[k];
combo += deck[m];
combo += deck[n];
bighands.push(combo);
}
}
}
}
}
有效,我只想要一个 better/more 通用方法。
使用生成器可以非常优雅地实现这一点:
function* loop(depth, start, times, prev = []) {
if(depth <= 0) {
yield prev;
return;
}
for(let current = start; current < times; current++) {
yield* loop(depth - 1, current + 1, times, [...prev, current]);
}
}
可用作:
for(const [j, k, l, m] of loop(4, /*times from*/ 0, /* till*/ 5)) {
//...
}
以上将以与 for 循环相同的方式进行迭代,当然您可以使用生成器做更多的事情,例如直接生成组合:
const identity = _ => _;
function* take(n, of, mapper = identity, prev = []) {
if(!of.length) return;
if(prev.length >= n) {
yield mapper(prev);
return;
}
for(let i = 0; i < of.length; i++) {
yield* take(n, of slice(i + 1), mapper, [...prev, of[i]]);
}
}
for(const combo of take(4, /*of*/ deck, it => it.reduce((a, b) => a + b))) {
//...
}
或者如果你直接需要一个数组
function toArray(iterator) {
let result = [], value;
while(!({ value } = iterator.next()).done) result.push(value);
return result;
}
const combos = toArray(take(4, /*of*/ deck, it => it.reduce((a, b) => a + b)));
您可以采用递归方法。
function getHands(array, size, right = []) {
return array.reduce((r, v, i, a) => {
var temp = [...right, v];
if (temp.length === size) {
r.push(temp.join(' '));
} else {
r.push(...getHands(a.slice(i + 1), size, temp));
}
return r;
}, []);
}
var deck = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
bighands = getHands(deck, 5);
console.log(bighands.length);
console.log(bighands);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我正在尝试为自己编写一个扑克计算器,我有一个 5 级深的 for 循环。
为此,我一个接一个地嵌套了 for 循环。我正在寻找一种方法来简单地使用一个循环(或函数),它可以告诉我想去多少层。对于这个例子,答案是 5,但对于其他例子,它可能是一个更高(更高)的数字,这会很麻烦。我认为递归是一种实现它的方法我只是不知道如何设置它(不太了解递归)。非常感谢您的帮助。
for(var i=0; i < deck.length; i++){
for(var j=i+1; j<deck.length; j++){
for(var k=j+1; k<deck.length;k++){
for(var m=k+1; m<deck.length;m++){
for(var n=m+1; n<deck.length;n++){
combo = deck[i];
combo += deck[j];
combo += deck[k];
combo += deck[m];
combo += deck[n];
bighands.push(combo);
}
}
}
}
}
有效,我只想要一个 better/more 通用方法。
使用生成器可以非常优雅地实现这一点:
function* loop(depth, start, times, prev = []) {
if(depth <= 0) {
yield prev;
return;
}
for(let current = start; current < times; current++) {
yield* loop(depth - 1, current + 1, times, [...prev, current]);
}
}
可用作:
for(const [j, k, l, m] of loop(4, /*times from*/ 0, /* till*/ 5)) {
//...
}
以上将以与 for 循环相同的方式进行迭代,当然您可以使用生成器做更多的事情,例如直接生成组合:
const identity = _ => _;
function* take(n, of, mapper = identity, prev = []) {
if(!of.length) return;
if(prev.length >= n) {
yield mapper(prev);
return;
}
for(let i = 0; i < of.length; i++) {
yield* take(n, of slice(i + 1), mapper, [...prev, of[i]]);
}
}
for(const combo of take(4, /*of*/ deck, it => it.reduce((a, b) => a + b))) {
//...
}
或者如果你直接需要一个数组
function toArray(iterator) {
let result = [], value;
while(!({ value } = iterator.next()).done) result.push(value);
return result;
}
const combos = toArray(take(4, /*of*/ deck, it => it.reduce((a, b) => a + b)));
您可以采用递归方法。
function getHands(array, size, right = []) {
return array.reduce((r, v, i, a) => {
var temp = [...right, v];
if (temp.length === size) {
r.push(temp.join(' '));
} else {
r.push(...getHands(a.slice(i + 1), size, temp));
}
return r;
}, []);
}
var deck = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
bighands = getHands(deck, 5);
console.log(bighands.length);
console.log(bighands);
.as-console-wrapper { max-height: 100% !important; top: 0; }