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.
CodePudding user response:
The problem is that:
your
console.log
should only be executed at the deepest level. So put thatconsole.log
in anelse
clause.The base case happens when
loopNumber === maxNestedLoops - 1
as that is the last index of your array, so theif
condition should correspond to that
if (loopNumber < maxNestedLoops - 1){
looper(loopNumber 1);
} else {
console.log(indexes);
}
CodePudding user response:
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);
CodePudding user response:
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);