Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nested for loops and multidimensional arrays

I'm trying to get my head around how nested for loops work with multidimensional arrays in JavaScipt and I'm a bit stuck on one point. Using a stock example

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]);
    }
}

This outputs 1 2 3 4 5 6 which is what I expected. However if I add numbers to the end of the outer array:

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

I still get the same output of 1 2 3 4 5 6 ? ? I am confused why 7 & 8 are not being picked up by the loop. Interestingly, if I use strings instead:

var arr = [["a","b"], ["c","d"], "y", "z"];
for (var i=0; i < arr.length; i++) {
    for (var j=0; j < arr[i].length; j++) {
        console.log(arr[i][j]);
    }
}

The output is a b c d y z, which is what I expected. Why does it behave differently for strings?

like image 488
quietplace Avatar asked Mar 06 '23 19:03

quietplace


1 Answers

As others have mentioned, your inner loop is all about iterating the arrays found in the top level (non-nested array). It makes the assumption that all the elements in the top-level array will be nested arrays, which isn't the case. (You need to make sure that you have an array before attempting to iterate through it.) Since 7 and 8 in the top level aren't arrays, arr[i].length returns undefined for numbers, but strings are "array like" objects and do have a length property. A string of "y" has a length of 1 and so the inner loop works because it starts from zero and obtains the character at position zero in the string "array" of "y", which is "y".

But, this is a good reason not to use traditional for loops with arrays when we now have Array.forEach(), which eliminates the need for indexes to be manually managed and allows us to access the value being enumerated directly without worrying about indexes.

var arr = [[1,2], [3,4], [5,6], 7, 8];
var output = "";

// Enumerate the top-level array:
arr.forEach(function(value){
  // Check to see if the item is an array
  if(value instanceof Array){
    // If so, enuerate that nested array
    value.forEach(function(nestedValue){
      // Add the nested array's value to the output
      output += nestedValue + " " ;
    });
  } else {
    // Item is not an array, just add its value to the output
    output += value + " ";
  }
});

console.log(output);

Oh, and by the way, I realize that this is not what you were asking about, but just as an FYI, here's a way to obtain all the values without any loops:

console.log([[1,2], [3,4], [5,6], 7, 8].toString().split(",").join(" "));
like image 114
Scott Marcus Avatar answered Mar 30 '23 08:03

Scott Marcus