1

I'm having a trouble when I want to create a multidimensional array.

I don't know why but I get a strange behavior when I want to create a multidimensional array with an object as default value.

I have used different ways like:

The trouble appears when I want to change anyone of fields of the object.

function matrix( rows, cols, defaultValue){
  var arr = [];
  // Creates all lines:
  for(var i=0; i < rows; i++){
      // Creates an empty line
      arr.push([]);
      // Adds cols to the empty line:
      arr[i].push( new Array(cols));
      for(var j=0; j < cols; j++){
        // Initializes:
        arr[i][j] = defaultValue;
      }
  }
 return arr;
}

var myArray = matrix(5, 5, {
 status: 'OK'
});


myArray[2][1].status = 'NOT OK';

console.log('Strange behavior', myArray);

The change expands on the other positions.

Can anybody help me?

Community
  • 1
  • 1
saeta
  • 4,048
  • 2
  • 31
  • 48

4 Answers4

3

Because you store a reference to one and the same object over and over again, you have the behaviour as you described. To get separate objects, you could use object.assign, to make a (shallow) copy of defaultValue each time you need it:

arr[i][j] = Object.assign({}, defaultValue);

With some other ES6 features, your code could look like this:

function matrix( rows, cols, defaultValue){
  return Array.from(Array(rows), 
     row => Array.from(Array(cols), cell => Object.assign({}, defaultValue))
  );
}
var myArray = matrix(5, 5, {
 status: 'OK'
});

myArray[2][1].status = 'NOT OK';

console.log('Correct behavior', myArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
trincot
  • 317,000
  • 35
  • 244
  • 286
2

The problem is you're assigning the same object at each point in the matrix. So if you change the object at one point in the array, it will be changed at all other points as well. To fix, use a clone function (like underscore's or jQuery's) or instantiate a new object for each point in the matrix.

tanenbring
  • 780
  • 4
  • 14
0

Instead of

arr.push([]);
// Adds cols to the empty line:
arr[i].push( new Array(cols));

try

arr.push( new Array(cols));
Vaibhav Nigam
  • 1,334
  • 12
  • 21
0

Objects are passed around by their references, so you are assigning a reference to the same object to all the cells in the matrix thus making them all the same object (changing one will cause the others to change as well). You'll have to duplicate the object. If you are using recent ECMAScripts you can use Object.assign like this:

function matrix( rows, cols, defaultValue) {
  var arr = [];
  for(var i=0; i < rows; i++) {
      var row = [];  // create a row
      arr.push(row); // push it into the matrix

      for(var j=0; j < cols; j++) {
        row[j] = Object.assign({}, defaultValue); // copy the default value and assign it to this cell
      }
  }
    return arr;
}
ibrahim mahrir
  • 31,174
  • 5
  • 48
  • 73