Is there a more concise way to initialize empty multidimensional arrays?
Asked Answered
S

6

14

I've been trying to find a reasonably concise way to set the dimensions of an empty multidimensional JavaScript array, but with no success so far.

First, I tried to initialize an empty 10x10x10 array using var theArray = new Array(10, 10 10), but instead, it only created a 1-dimensional array with 3 elements.

I've figured out how to initialize an empty 10x10x10 array using nested for-loops, but it's extremely tedious to write the array initializer this way. Initializing multidimensional arrays using nested for-loops can be quite tedious: is there a more concise way to set the dimensions of empty multidimensional arrays in JavaScript (with arbitrarily many dimensions)?

//Initializing an empty 10x10x10 array:
var theArray = new Array();
for(var a = 0; a < 10; a++){
    theArray[a] = new Array();
    for(var b = 0; b < 10; b++){
        theArray[a][b] = new Array();
        for(var c = 0; c < 10; c++){
            theArray[a][b][c] = 10
        }
    }
}

console.log(JSON.stringify(theArray));
Silicium answered 21/7, 2013 at 19:41 Comment(7)
The Java programming language has int[][] stuff = new int[10][10], but I'm not aware of any similar construct in JavaScript.Silicium
possible duplicate of How can I create a two dimensional array in JavaScript?Blotter
@Blotter No, this question is asking how to initialize arrays of arbitrarily many dimensions, not just 2 dimensions.Silicium
There is no better way. Your solution is fine.Telemechanics
@Pumbaa80 I'm sure there's a better way: the solutions below are much more concise than the solution that I found, and they can be used to create arrays with any number of dimensions.Silicium
@AndersonGreen Right, I missed the "arbitrary many dimensions" part. If you just need one 3dimensional array, a generic function may be overkillTelemechanics
+1 for an actually good question with a fun coding challenge!Lorettalorette
S
6

Adapted from this answer:

function createArray(length) {
  var arr = new Array(length || 0),
      i = length;
    
  if (arguments.length > 1) {
    var args = Array.prototype.slice.call(arguments, 1);
    while(i--) arr[i] = createArray.apply(this, args);
  }        
  return arr;
 }

Simply call with an argument for the length of each dimension. Usage examples:

  • var multiArray = createArray(10,10,10); Gives a 3-dimensional array of equal length.
  • var weirdArray = createArray(34,6,42,2); Gives a 4-dimensional array of unequal lengths.
Suspicious answered 21/7, 2013 at 19:57 Comment(1)
you can simplify your while using the one i did in my answerSelfridge
B
3
function multiDimArrayInit(dimensions, leafValue) {
    if (!dimensions.length) {
        return leafValue;
    }
    var arr = [];
    var subDimensions = dimensions.slice(1);
    for (var i = 0; i < dimensions[0]; i++) {
        arr.push(multiDimArrayInit(subDimensions, leafValue));
    }
    return arr;
}


console.log(multiDimArrayInit([2,8], "hi")); // counting the nested "hi"'s yields 16 of them

demo http://jsfiddle.net/WPrs3/

Brilliantine answered 21/7, 2013 at 20:0 Comment(1)
Good job, two minor nitpicks: callee is deprecated and it's better to move slice out of the loop.Earl
L
1

Here is my take on the problem: nArray utility function

function nArray() {
    var arr = new Array();
    var args = Array.prototype.slice.call(arguments, 1);
    for(var i=0;i<arguments[0];i++) {
        arr[i] = (arguments.length > 1 && nArray.apply(this, args)) || undefined;
    }
    return arr;
}

Usage example:

var arr = nArray(3, 3, 3);

Results in 3x3x3 array of undefined values.

Running code with some tests also available as a Fiddle here: http://jsfiddle.net/EqT3r/7/

Lorettalorette answered 21/7, 2013 at 19:58 Comment(0)
C
0

The more dimension you have, the more you have interest in using one single flat array and a getter /setter function for your array.
Because for a [d1 X d2 X d3 X .. X dn] you'll be creating d2*d3*...*dn arrays instead of one, and when accessing, you'll make n indirection instead of 1.

The interface would look like :

var myNArray = new NArray(10,20,10);
var oneValue = myNArray.get(5,8,3);
myNArray.set(8,3,2, 'the  value of (8,3,2)');

the implementation depends on your preference for a fixed-size n-dimensionnal array or an array able to push/pop and the like.

Coca answered 23/7, 2013 at 19:43 Comment(0)
D
0

A more succinct version of @chris code:

function multiDim (dims, leaf) {
  dims = Array.isArray (dims) ? dims.slice () : [dims];
  return Array.apply (null, Array (dims.shift ())).map (function (v, i) {
    return dims.length 
      ? multiDim (dims, typeof leaf == 'string' ? leaf.replace ('%i', i + ' %i') : leaf)
      : typeof leaf == 'string' ? leaf.replace ('%i', i) : leaf;
  });      
}

console.log (JSON.stringify (multiDim ([2,2], "hi %i"), null, '  ')); 

Produces :

[
  [
    "hi 0 0",
    "hi 0 1"
  ],
  [
    "hi 1 0",
    "hi 1 1"
  ]
]

In this version you can pass the first argument as a number for single dimension array. Including %i in the leaf value will provide index values in the leaf values.

Play with it at : http://jsfiddle.net/jstoolsmith/r3eMR/

Darladarlan answered 24/7, 2013 at 9:18 Comment(0)
N
0

Very simple function, generate an array with any number of dimensions. Specify length of each dimension and the content which for me is '' usually

function arrayGen(content,dims,dim1Len,dim2Len,dim3Len...) {
  var args = arguments;
  function loop(dim) {
    var array = [];
    for (var a = 0; a < args[dim + 1]; a++) {
      if (dims > dim) {
        array[a] = loop(dim + 1);
      } else if (dims == dim) {
        array[a] = content;
      }
    }
    return array;
  }
  var  thisArray = loop(1);
  return thisArray;
};

I use this function very often, it saves a lot of time

Nakano answered 6/2, 2015 at 0:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.