Reputation: 6512
Suppose I have this pattern:
for(let i =0; i < 3; i++){
for(let j =0; j < 3; j++){
for(let k =0; k < 3; k++){
console.log(i,j,k)
}
}
}
Benefit is I have access to all iteration variables within innermost loop. i
, j
, and k
, disadvantage is it is hardcoded to 3 levels of nested loops. If I want a fourth I need to add that code manually.
I am trying to generalize the code using recursion where I can set the number of nested loops to an arbitrary variable. Here is what I am trying:
const maxNestedLoops = 3;
const iterations = 3;
const indexes = [];
function looper(loopNumber){
for(indexes[loopNumber] = 0; indexes[loopNumber] < iterations; indexes[loopNumber]++){
if(loopNumber < maxNestedLoops){
looper(loopNumber + 1);
}
console.log(indexes);
}
}
looper(0);
The first results in the following in the console:
0, 0, 0
0, 0, 1
0, 0, 2
0, 1, 0
0, 1, 1
0, 1, 2
0, 2, 0
0, 2, 1
0, 2, 2
...and so on
However with my recursive function example it is not the same:
[0, 0, 0, 0]
[0, 0, 0, 1]
[0, 0, 0, 2]
[0, 0, 0, 3]
[0, 0, 1, 0]
[0, 0, 1, 1]
[0, 0, 1, 2]
[0, 0, 1, 3]
[0, 0, 2, 0]
[0, 0, 2, 1]
[0, 0, 2, 2]
[0, 0, 2, 3]
[0, 0, 3, 3]
...and so on
Problems are that not only are there four indexes instead of three. But some of the values are 3
s and I would expect it to only go up to 2
.
Advice appreciated.
Upvotes: 2
Views: 250
Reputation: 304
Here you go. It was a interesting one :)
const maxNestedLoops = 3;
const iterations = 3;
const indexes = [];
function looper(level){
for (let i=0; i<iterations; i++){
indexes.push(i);
if (level === maxNestedLoops-1) {
console.log(indexes);
indexes.splice(level,1);
continue;
}
looper(level + 1);
indexes.splice(level,1);
}
}
looper(0);
Upvotes: 1
Reputation: 16785
There is problem with the for
loop. indexes[loopNumber]++
will be increased until it will reach the value of iterations
. Since your value of iterations is 3
, you will end up with values which are equal to 3
in the indexes
array, because the loop itself is modifying the array.
Also, since you modify your array if indexes before checking if the loopNumber
reached the number of maxNestedLoops
, you will end up with an array with length of maxNestedLoops + 1
.
What I suggest you should do:
const maxNestedLoops = 3;
const iterations = 3;
const indexes = [];
function looper(loopNumber) {
// Check if we reached the number of nested loops before doing anything else.
if (loopNumber < maxNestedLoops) {
// Don't modify the indexes array directly, use a variable instead
for (let i = 0; i < iterations; i++) {
indexes[loopNumber] = i;
looper(loopNumber + 1);
console.log(indexes);
}
}
}
looper(0);
Upvotes: 1
Reputation: 350365
The problem is that:
your console.log
should only be executed at the deepest level. So put that console.log
in an else
clause.
The base case happens when loopNumber === maxNestedLoops - 1
as that is the last index of your array, so the if
condition should correspond to that
if (loopNumber < maxNestedLoops - 1){
looper(loopNumber + 1);
} else {
console.log(indexes);
}
Upvotes: 1