Nested For Loops

Hey all. First time poster on FCC. I tried algorithm scripting with high difficulties like others. So I wanted to take a step back and look at nested for loops to increase my understanding. I’m attempted to printout a solution like this:



*
**
***
****
*****
function nestedLoop(arr){
   outter:for(let i = 0; i < arr.length; i++){

     console.log([i]); 

    inner:for(let j = 0; j < arr.length; j++){

       return([j]); 

     }

   }

}

console.log(nestedLoop(10));

would someone be able to guide me into why I am getting undefined, and/if i’m right track without giving the answer away? Thanks guys!

Nested for loops are weird. I think the best way to think of it is to just follow our rules.

A for loop is just a way to do something over and over again until we reach some condition. Basically we’re stuck in our block of code in our for loop until the for loop is finished executing. So, when we start:

We’ve entered our first for loop. We do our initialization of i and then we check our stopping condition i < arr.length;, if it’s false we exit, but if it’s true we enter the loop. Because we’re initializing we don’t execute our incrementation step i++ until the next loop.

Remember we execute our program line by line, so of course the next thing is console.log([i]). Which will just print whatever number i is currently.

And after this we encounter our nested loop. inner:for(let j = 0; j < arr.length; j++). Basically, before we are able to step our outer loop, we need to have finished executing this block of code and the only way the inner for loop is going to finish executing is if we run through the exact same steps as we did for the outer one, i.e. we need to execute UNTIL our stopping condition. This is why our inner for loop will run a complete cycle because for loops always run until they’re finished and that’s exactly why when we nest them we get this behavior:

0 -> 0, 1, 2, 3, ... , arr.length
1 -> 0, 1 , 2, 3, ... , arr.length
...

I hope that didn’t confuse you more lol.

Thanks @stutterz I am not quite sure I got all of that, but what I do think I understood was, to perhaps not do an empty array for this challenge and just use a number to see the pattern.

I do seem to get a staggard pattern with this, but am still unsure.

function nestedLoop(){
   outter:for(let i = 0; i < 10; i++){
     console.log([i]); 
     inner:for(let j = 0; j < 10; j++){
       console.log([j]);
      }
     }
   }


console.log(nestedLoop(10)); ```

Step back for a moment and think about what we use non-nested loops for. We use for loops for single-dimensional data structures, like the following list of integers in the fibonacci sequence:

[1, 1, 2, 3, 5]

Notice that the data is sequential, linear, ordered. If we use a for loop, we can step through the indeces of this array one by one.


Now let’s imagine our data structure is two-dimensional. When I think two-dimensional, I think of a square or rectangle, something with a width and height. Let’s imagine a tic-tac-toe board. It could be represented with a two-dimensional array in JavaScript (in this case an array of arrays of strings).

[
  ["X", "O", "X"],
  [" ", "X", " "],
  ["O", " ", "X"]
]

With this data structure, we can use a for loop to step through each row sequentially, and a nested for loop to step through each item in said row.

const board = [
  ["X", "O", "X"],
  [" ", "X", " "],
  ["O", " ", "X"]
];

for (let y = 0; y < board.length; y++) {
  const row = board[y];
  for (let x = 0; x < row.length; x++) {
    const item = row[x];
    console.log(item);
  }
}

/* outputs:
X
O
X
 
X
 
O
 
X
*/

Another example of a two-dimensional data structure could be an English sentence. Let’s take the sentence “I am not Greg”. We can use the split method on strings to separate the words into an array (the outer loop), and then loop through each character in each word.

const sentence = "I am not Greg";
const words = sentence.split(" "); // ["I", "am", "not", "Greg"];

for (let i = 0; i < words.length; i++) {
  const word = words[i];
  for (let j = 0; j < word.length; j++) {
    const char = word[j];
    console.log(char);
  }
}

/* outputs:
I
a
m
n
o
t
G
r
e
g
*/

Does this help?

3 Likes

This was definitely a better explanation. colin is a beast…

I would just look at Colin’s answer. I think his explanation makes more sense.

1 Like

Thanks for the detailed nudge @colinthornton. This may be a little bit outside my realm of understanding, I think I understand what you’re saying but I still am a little confused as my setup is rather similar to your code but my console.log is not printing in the goal of the challenge:

function nestedLoop(){

 let mapOfStars = [

   ['*'],

   ['*','*'],

   ['*','*','*'],

   ['*','*','*','*']

   ];

  outter:for(let i = 0; i < mapOfStars.length; i++){

       let row = mapOfStars[i]

    inner:for(let j = 0; j < row.length; j++){

       let finalResult = row[j];

       return(finalResult); 

     }

    }

  }

console.log(nestedLoop());

You’ve got a few syntax errors that I’ll point out next, but first I just want to check what the goal of this function is. Do you mind elaborating what it is you want to achieve?

It is off the W3 website for for loops practice

10. Write a JavaScript program to construct the following pattern, using a nested for loop. Go to the editor

but essentially i need to use a for loop to print this specific pattern:

*
**
***
****
*****
******

Ah, so in this case you’re not working on input data, you just want to build up the data as you go.

Similar to the examples I gave above, the outer loop will be for the rows, while the inner loop will be for the columns (stars).

Notice that the amount of stars in a row relate to its row number.

| row | stars |
|   0 |     1 |
|   1 |     2 |
|   2 |     3 |
|   3 |     4 |
|   4 |     5 |
|   5 |     6 |

Here’s some starter code:

for (let row = 0; row < 6; row++) {
  /* declare a stars string */
  for (let col = 0; col < /* ? */; col++) {
    /* add a "*" to the stars string */
  }
  /* print the stars string */
}

Sorry if this is too much of a hint…

Surprisingly no I still don’t think I quite understand!

function starLooper(){
  for(let row = 0; row < 6; row++){
    let stars = ' ';
    for (let col = 0 ; col < row.length; col++){
       stars += ('*')
    }
    return stars; 
  }
}

console.log(starLooper());

So i made an empty string, and then am incrimenting it by adding the “" with every iteration. But I get an empty string in the return as if the * is not getting added. Should I be using an array and pushing the "” to it?

let stars = ' ';

If you initialize the string with a space in it, with the plan to concatenate stars, then the result will be

 *
 **
 ***

and so on, instead of

*
**
***

which, while only a small difference, is technically wrong.


for (let col = 0 ; col < row.length; col++){

A couple things here. The row value is an integer that represents which row from the top you’re currently working on. As it is of the type number, it does not have a length property. You’ll need to use the value of row directly to create the correct relation (how many stars should be on a row, based on its row number?).


stars += ('*')

It’s technically okay to use the parentheses here, but they’re unnecessary and make it more difficult to parse than should be. stars += '*' is enough.


return stars; 

The return keyword immediately exits from the function, even in the middle of a loop, so in this case you’re only ever making one single iteration of the outer loop. I would instead call console.log on each iteration of the outer loop. Remember, this is a function to print that star pattern to the console, it is not a function that returns a value to be printed.

If you make that change, then likewise you’ll need to change the console.log(starLooper()) line to just starLooper() (and at which point you should probably change the name of the function to something like printStars).

1 Like
function printStars(){
  for(let row = 0; row < 6; row++){
    let stars = '';
    for (let col = 0 ; col < row ; col++){
       stars += '*'
    }
    console.log(stars); 
  }
}

printStars(); 

You are the best! Super props and thank you for your utmost patience with me. Your explanations are a real help. If you have any recommendations on how I can continue to work on loop challenges of some kind I would love your input. Thank you again!

Great job!

As an extension of this one, can you make the function more generic, so that it accepts an argument for the number of rows to print?

So printStars(3) should output

*
**
***

and printStars(5) should output

*
**
***
****
*****

Like this?

function printStars(x){
  for(let row = 0; row <= x; row++){
    let stars = '';
    for (let col = 0 ; col < row ; col++){
       stars += '*'
    }
    console.log(stars); 
  }
}
printStars(3)
printStars(5); 

1 Like

Don’t ask me, test it out in your browser console!

Lol. It looks good on my end I see it printing staggard so it looks good to me. See these are fun, I need to work through more problems on FCC. Discord does not have the level of help that FCC does. Thanks @colinthornton

doesn’t it print four lines if you write printStars(3)? I would expect just three lines myself

No It will print two if I enter printStars(3). Unless I set the first forloop to row <= x, then I get 3 lines