[javascript] For loop in multidimensional javascript array

Since now, I'm using this loop to iterate over the elements of an array, which works fine even if I put objects with various properties inside of it.

var cubes[];

for (i in cubes){
     cubes[i].dimension
     cubes[i].position_x
     ecc..
}

Now, let's suppose cubes[] is declared this way

var cubes[][];

Can I do this in Javascript? How can I then automatically iterate in

cubes[0][0]
cubes[0][1]
cubes[0][2]
cubes[1][0]
cubes[1][1]
cubes[1][2]
cubes[2][0]
ecc...

As a workaround, I can just declare:

var cubes[];
var cubes1[];

and work separately with the two arrays. Is this a better solution?

This question is related to javascript loops multidimensional-array

The answer is


You can do something like this:

var cubes = [
 [1, 2, 3],
 [4, 5, 6],    
 [7, 8, 9],
];

for(var i = 0; i < cubes.length; i++) {
    var cube = cubes[i];
    for(var j = 0; j < cube.length; j++) {
        display("cube[" + i + "][" + j + "] = " + cube[j]);
    }
}

Working jsFiddle:

The output of the above:

cube[0][0] = 1
cube[0][1] = 2
cube[0][2] = 3
cube[1][0] = 4
cube[1][1] = 5
cube[1][2] = 6
cube[2][0] = 7
cube[2][1] = 8
cube[2][2] = 9

var cubes = [["string", "string"], ["string", "string"]];

for(var i = 0; i < cubes.length; i++) {
    for(var j = 0; j < cubes[i].length; j++) {
        console.log(cubes[i][j]);
    }
}

JavaScript does not have such declarations. It would be:

var cubes = ...

regardless

But you can do:

for(var i = 0; i < cubes.length; i++)
{
  for(var j = 0; j < cubes[i].length; j++)
  {

  }
}

Note that JavaScript allows jagged arrays, like:

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

since arrays can contain any type of object, including an array of arbitrary length.

As noted by MDC:

"for..in should not be used to iterate over an Array where index order is important"

If you use your original syntax, there is no guarantee the elements will be visited in numeric order.


Try this:

var i, j;

for (i = 0; i < cubes.length; i++) {
    for (j = 0; j < cubes[i].length; j++) {
       do whatever with cubes[i][j];
    }
}

An efficient way to loop over an Array is the built-in array method .map()

For a 1-dimensional array it would look like this:

function HandleOneElement( Cuby ) {
   Cuby.dimension
   Cuby.position_x
   ...
}
cubes.map(HandleOneElement) ; // the map function will pass each element

for 2-dimensional array:

cubes.map( function( cubeRow ) { cubeRow.map( HandleOneElement ) } )

for an n-dimensional array of any form:

Function.prototype.ArrayFunction = function(param) {
  if (param instanceof Array) {
    return param.map( Function.prototype.ArrayFunction, this ) ;
  }
  else return (this)(param) ;
}
HandleOneElement.ArrayFunction(cubes) ;

If you're using ES2015 and you want to define your own object that iterates like a 2-D array, you can implement the iterator protocol by:

  1. Defining an @@iterator function called Symbol.iterator which returns...
  2. ...an object with a next() function that returns...
  3. ...an object with one or two properties: an optional value with the next value (if there is one) and a boolean done which is true if we're done iterating.

A one-dimensional array iterator function would look like this:

// our custom Cubes object which implements the iterable protocol
function Cubes() {
    this.cubes = [1, 2, 3, 4];
    this.numVals = this.cubes.length;

    // assign a function to the property Symbol.iterator
    // which is a special property that the spread operator
    // and for..of construct both search for
    this[Symbol.iterator] = function () { // can't take args

        var index = -1; // keep an internal count of our index
        var self = this; // access vars/methods in object scope

        // the @@iterator method must return an object
        // with a "next()" property, which will be called
        // implicitly to get the next value
        return {
            // next() must return an object with a "done" 
            // (and optionally also a "value") property
            next: function() {
                index++;
                // if there's still some values, return next one
                if (index < self.numVals) {
                    return {
                        value: self.cubes[index],
                        done: false
                    };
                }
                // else there's no more values left, so we're done
                // IF YOU FORGET THIS YOU WILL LOOP FOREVER!
                return {done: true}
            }
        };
    };
}

Now, we can treat our Cubes object like an iterable:

var cube = new Cubes(); // construct our cube object

// both call Symbol.iterator function implicitly:
console.log([...cube]); // spread operator
for (var value of cube) { // for..of construct
    console.log(value);
}

To create our own 2-D iterable, instead of returning a value in our next() function, we can return another iterable:

function Cubes() {
    this.cubes = [
        [1, 2, 3, 4],
        [5, 6, 7, 8],
        [9, 10, 11, 12],
    ];
    this.numRows = this.cubes.length;
    this.numCols = this.cubes[0].length; // assumes all rows have same length

    this[Symbol.iterator] = function () {
        var row = -1;
        var self = this;

        // create a closure that returns an iterator
        // on the captured row index
        function createColIterator(currentRow) {
            var col = -1;
            var colIterator = {}
            // column iterator implements iterable protocol
            colIterator[Symbol.iterator] = function() {
                return {next: function() {
                    col++;
                    if (col < self.numCols) {
                        // return raw value
                        return {
                            value: self.cubes[currentRow][col],
                            done: false
                        };
                    }
                    return {done: true};
                }};
            }
            return colIterator;
        }

        return {next: function() {
            row++;
            if (row < self.numRows) {
                // instead of a value, return another iterator
                return {
                    value: createColIterator(row),
                    done: false
                };
            }
            return {done: true}
        }};
    };
}

Now, we can use nested iteration:

var cube = new Cubes();

// spread operator returns list of iterators, 
// each of which can be spread to get values
var rows = [...cube];
console.log([...rows[0]]);
console.log([...rows[1]]);
console.log([...rows[2]]);

// use map to apply spread operator to each iterable
console.log([...cube].map(function(iterator) { 
    return [...iterator];
}));

for (var row of cube) {
    for (var value of row) {
        console.log(value);
    }
}

Note that our custom iterable won't behave like a 2-D array in all cases; for example, we haven't implemented a map() function. This answer shows how you could implement a generator map function (see here for the difference between iterators and generators; also, generators are an ES2016 feature, not ES2015, so you'll need to change your babel presets if you're compiling with babel).


Or you can do this alternatively with "forEach()":

var cubes = [
 [1, 2, 3],
 [4, 5, 6],    
 [7, 8, 9],
];

cubes.forEach(function each(item) {
  if (Array.isArray(item)) {
    // If is array, continue repeat loop
    item.forEach(each);
  } else {
    console.log(item);
  }
});

If you need array's index, please try this code:

var i = 0; j = 0;

cubes.forEach(function each(item) {
  if (Array.isArray(item)) {
    // If is array, continue repeat loop
    item.forEach(each);
    i++;
    j = 0;
  } else {
    console.log("[" + i + "][" + j + "] = " + item);
    j++;
  }
});

And the result will look like this:

[0][0] = 1
[0][1] = 2
[0][2] = 3
[1][0] = 4
[1][1] = 5
[1][2] = 6
[2][0] = 7
[2][1] = 8
[2][2] = 9

A bit too late, but this solution is nice and neat

const arr = [[1,2,3],[4,5,6],[7,8,9,10]]
for (let i of arr) {
  for (let j of i) {
    console.log(j) //Should log numbers from 1 to 10
  }
}

Or in your case:

const arr = [[1,2,3],[4,5,6],[7,8,9]]
for (let [d1, d2, d3] of arr) {
  console.log(`${d1}, ${d2}, ${d3}`) //Should return numbers from 1 to 9
}

Note: for ... of loop is standardised in ES6, so only use this if you have an ES5 Javascript Complier (such as Babel)

Another note: There are alternatives, but they have some subtle differences and behaviours, such as forEach(), for...in, for...of and traditional for(). It depends on your case to decide which one to use. (ES6 also has .map(), .filter(), .find(), .reduce())


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to loops

How to increment a letter N times per iteration and store in an array? Angular 2 Cannot find control with unspecified name attribute on formArrays What is the difference between i = i + 1 and i += 1 in a 'for' loop? Prime numbers between 1 to 100 in C Programming Language Python Loop: List Index Out of Range JavaScript: Difference between .forEach() and .map() Why does using from __future__ import print_function breaks Python2-style print? Creating an array from a text file in Bash Iterate through dictionary values? C# Wait until condition is true

Examples related to multidimensional-array

what does numpy ndarray shape do? len() of a numpy array in python What is the purpose of meshgrid in Python / NumPy? Convert a numpy.ndarray to string(or bytes) and convert it back to numpy.ndarray Typescript - multidimensional array initialization How to get every first element in 2 dimensional list How does numpy.newaxis work and when to use it? How to count the occurrence of certain item in an ndarray? Iterate through 2 dimensional array Selecting specific rows and columns from NumPy array