21

I'm learning JavaScript at the moment on freecodecamp and they have an example for nested for loops in one of their excercises:

 var arr = [[1,2], [3,4], [5,6]];
 for (var i=0; i < arr.length; i++) {
  for (var j=0; j < arr[i].length; j++) {
    console.log(arr[i][j]);
  }
}

With console.log = 1 2 3 4 5 6 undefined.

I understand for loops more or less, and I understand that [i] and [j] are used to access the array (I think?). I just don't understand why at the end it just prints out those numbers? I found this question asked a few years back but it just explains how to write them, not how they work:

For loop in multidimensional javascript array

I broke it down into:

var arr = [  [1,2], [3,4], [5,6]];for (var i=0; i < arr.length; i++) {
 console.log(arr[i]);}

Which prints out

[ 1, 2 ]
[ 3, 4 ]
[ 5, 6 ]
undefined

and

var arr = [  [1,2], [3,4], [5,6]];
for (var i=0; i < arr.length; i++) {  
 for (var j=0; j < arr[i].length; j++) {    
  console.log(arr[i]);  }}

which prints out:

[ 1, 2 ]
[ 1, 2 ]
[ 3, 4 ]
[ 3, 4 ]
[ 5, 6 ]
[ 5, 6 ]
undefined

and

var arr = [  [1,2], [3,4], [5,6]];
 for (var i=0; i < arr.length; i++) {  
  for (var j=0; j < arr[i].length; j++) {    
   console.log(arr[j]);  }}

which prints out

[ 1, 2 ]
[ 3, 4 ]
[ 1, 2 ]
[ 3, 4 ]
[ 1, 2 ]
[ 3, 4 ]
undefined

I understand the first two arr[i]. The loop iterates through the array and prints out the individual elements (in this case an array) and in the second one I guess it just does it twice because there are two loops. What I don't understand is:

  1. why the last array in arr[j] is not printed out (where did the [5, 6] go?)
  2. why arr[i][j] suddenly eliminates the arrays and just prints out the numbers
  3. where the 'undefined' comes from

Could anyone help me out with this and explain the steps the code takes before printing it out in the console? I would really like to understand it but don't even know how to search for this question the right way.

Community
  • 1
  • 1
stellatores
  • 213
  • 1
  • 2
  • 6
  • 3
    Don't worry about the `undefined` at the end; that's a by-product of how `console.log()` interprets the code. – Pointy Apr 04 '16 at 21:26
  • 2
    That is not correct Pointy. The reason stellatores is getting an undefined at the end is because he is incrementing i on the last for loop before it hits the j loop in order to hit the conditional. For loops will always run once and only stop when a condition is met. In this case, the last loop pushes i to equal 7, and there is no 7th position in the number array. This results in undefined, because the array position simply does not have a number assigned to it. – Korgrue Apr 04 '16 at 21:41
  • 1
    @Korgrue no, Pointy is right. The i loop only runs from 0 to 2 before terminating. The `undefined` is the return value of the `for` statement. `console.log('Hi')` does the same thing: it outputs 'Hi' and then undefined. – Stuart Apr 04 '16 at 21:54
  • And here I was thinking it was something to do with the code. Thanks – stellatores Apr 05 '16 at 20:19

7 Answers7

19
var arr = [[1,2], [3,4], [5,6]];

This is an array of arrays. It is a little bit easier to read like this:

var arr = [
            [1,2],
            [3,4],
            [5,6]
          ];

That makes it a little bit easier to see that you have an array of 3 arrays. The outer 'for' will loop through each of 1st level arrays. So the very first outer for loop when i=0 you are going to grab the first inner array [1,2]:

for (var i=0; i < arr.length; i++) {
    //First time through i=0 so arr[i]=[1,2];
}

In the inner loop you are going to loop through each of the 3 inner arrays one at a time.

for (var j=0; j < arr[i].length; j++) {
    //Handle inner array.
}

This argument grabs the length of the inner array:

arr[i].length

So on your first time through the outer loop i=0 and arr[i] is going to equal [1,2] because you are grabbing the 0th element. Remember, arrays elements are always counted starting at 0, not 1.

Finally you are printing out the results with:

console.log(arr[i][j]);

The first time through you can break it down a little. i=0 and j=0. arr[0][0] which translates as grab the first element from the outer array and then the first element from the first inner array. In this case it is '1':

[
    [1,2], <-- 0
    [3,4], <-- 1
    [5,6]  <-- 2
];

The code will loop through the first first set [1,2], then the second [3,4], and so on.

Gremash
  • 8,158
  • 6
  • 30
  • 44
  • Got it, so with arr[i][j] you actually first grab the inner array then the element inside the inner array and print it out, thanks! Your array[0][0] made it click. And console.log(arr[j]) actually doesn't print out the last inner array because it is dependent on arr[i] which are the inner arrays with a length of two so the counter stops before the third array. Thanks a lot! – stellatores Apr 05 '16 at 20:18
9

The double for loop you have above works like so:

 var arr = [[1,2], [3,4], [5,6]];

 for (var i=0; i < arr.length; i++) {
  // i = 0, then we loop below:
  for (var j=0; j < arr[i].length; j++) {
    //here we loop through the array which is in the main array
    //in the first case, i = 0, j = 1, then we loop again, i = 0, j = 1
    console.log(arr[i][j]);
    //after we finish the stuff in the 'j' loop we go back to the 'i' loop 
    //and here i = 1, then we go down again, i, remains at 1, and j = 0, then j = 1
    //....rinse and repeat, 
  }
}

In plain english:

We grab the first element in the main array, which is an array itself, we loop through that, and log at each index, this is terminated by our length condition in the second loop. We then move to to the next index of the main array, which is an array itself.... and so on, until we reach the end of the main array

To access and index in the main array, we need to use array[i] - that index holds an array - so to go INTO that array, we need to use array[i][j]

Hope that makes sense!

omarjmh
  • 13,632
  • 6
  • 34
  • 42
2

Despite some caveats of using for-in loops on arrays, they can imo sometimes help to clear the mess in nested loops a bit:

var arr = [[1,2], [3,4],[5,6]];

for (i in arr){
      for (j in arr[i]){
        console.log(arr[i][j]);
      }
    }

Also code visualization can clarify execution!

upgrd
  • 720
  • 7
  • 16
1

I know this is an old question... But because this is a popular post from ye olde google search, I feel it's helpful to add a way to visualize what's going on in nested for-loops.

As a JS teacher, I've found this method super helpful for visually-oriented people and those w/ dyslexia and related things).

// Original: https://repl.it/@justsml/nested-loop-visualizations
var nums = [[1,2,3], [4,5,6], [7,8,9]];

console.log('Example w/ Numbers:\n');
console.log('The array data: ', JSON.stringify(nums));

for (var i=0; i < nums.length; i++) {
  // Main/"top" array - accessing via "arr[i]"
  for (var j=0; j < nums[i].length; j++) {
    // here we loop through the "child" arrays
    let helpfulLabel = `nums[${i}][${j}]`
    let value = nums[i][j]
    console.log(helpfulLabel, 'Value=' + value);
  }
}

console.log('\nExample w/ String Data:\n');
var letters = [['a', 'b', 'c'], ['d', 'e', 'f'], ['x', 'y', 'z']];
console.log('The array data: ', JSON.stringify(letters));

for (var i=0; i < letters.length; i++) {
  for (var j=0; j < letters[i].length; j++) {
    let helpfulLabel = `letters[${i}][${j}]`
    let value = letters[i][j]
    console.log(helpfulLabel, 'Value=' + value);
  }
}

Preview of Results

repl results

Dan Levy
  • 1,214
  • 11
  • 14
1
function multiplyAll(arr) {
   var product = 1;
   // Only change code below this line
   for (var i = 0; i < arr.length; i++) {
     for (var j = 0; j < arr[i].length; j++) {
       product *= arr[i][j];
       console.log(product)
     }
   }
   // Only change code above this line
   return product;
 }
 // Modify values below to test your code
 multiplyAll([[1], [2], [3]])
 //multiplyAll([[1, 2], [3, 4], [5, 6, 7]]);
 //multiplyAll([[5, 1], [0.2, 4, 0.5], [3, 9]])
0
  1. why the last array in arr[j] is not printed out (where did the [5, 6] go?)

You may notice that if you print out j as console.log(j), it will print 6 times as 0, 1, 0, 1, 0, 1. And what you're trying to print is arr[j] which [5, 6] will not be displayed because its on arr[2]

  1. why arr[i][j] suddenly eliminates the arrays and just prints out the numbers

As you state there, arr is an array of 3 arrays. arr[i] represents 3 arrays either of [1, 2], [3, 4] or [5, 6]. And the j in arr[i][j] represents the index of those 3 arrays. This is called Multidimensional Array. arr[i][j] does not eliminate the array, but It selects the value in the index of j inside arr[i].

  1. where the 'undefined' comes from

It's just chrome thingy when you use console.log. Chrome returns undefined whenever you try to do that. Try to do it on firefox and you will see it no longer.

Community
  • 1
  • 1
choz
  • 17,242
  • 4
  • 53
  • 73
0
function multiply(arr) {
    var product = 1;

    for (var i = 0; i < arr.length; i++) {
        for (var j = 0; j < arr[i].length; j++) {
            product *= arr[i][j];
        }
    }

    return product;
}
סטנלי גרונן
  • 2,917
  • 23
  • 46
  • 68
samin
  • 482
  • 5
  • 9
  • Thank you for this code snippet, which might provide some limited, immediate help. A [proper explanation](https://meta.stackexchange.com/q/114762/349538) would greatly improve its long-term value by showing why this is a good solution to the problem and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you’ve made. – Ismael Padilla Jan 23 '20 at 20:23