OriolBG
OriolBG

Reputation: 2037

Modifying all arrays in a multi array

I'm trying to "paint" some grid with a rectangle area. But when I try to modify just one row the array modifies all of them. I tried to initialize the array in several ways, but the problem seems to be when I try to modify it, not the Array object.

var multiArray = Array(8).fill(Array(8).fill(false));

// Fill square 3x1 at (2, 4)
for (var i = 0; i < 3; i++) {
  for (var j = 0; j < 1; j++) {
    multiArray[2 + i][4 + j] = true;
  }
}

document.getElementById("content").innerHTML =
  multiArray.map(a => a.map(e => e ? 'X' : '0').join(''))
    .join('<br />');
<div id="content" />

At this point instead of providing a solution for this case I only want to understand why is that happening. What's the problem with [][] expression.

I'm trying this in Chrome version 51.0

Upvotes: 0

Views: 65

Answers (2)

Redu
Redu

Reputation: 26161

Creating an N dimension array is a little tricky since arrays are of reference types. I had done something as follows previously. The arrayND function takes sizes of each dimension as arguments and the last argument is the initializing value. I hope it helps.

Array.prototype.clone = function(){
  return this.map(e => Array.isArray(e) ? e.clone() : e);
};
function arrayND(...n){
  return n.reduceRight((p,c) => c = (new Array(c)).fill().map(e => Array.isArray(p) ? p.clone() : p ));
}
var arrND = arrayND(8,8,false);
console.log(arrND);

Upvotes: 0

nnnnnn
nnnnnn

Reputation: 150030

Array(8).fill(Array(8).fill(false)) only creates two arrays, one of which contains eight references to the other. This is more obvious if you break it into two lines - the following is equivalent:

var tempArray = Array(8).fill(false);
var multiArray = Array(8).fill(tempArray);

So that's not what you want. Try something like this instead:

var multiArray = Array(8).fill(0).map(_=>Array(8).fill(false));

I've filled the first array with zeros just as placeholders so that .map() will visit all of those elements, then for each element my little map callback returns a new array filled with false.

In context:

var multiArray = Array(8).fill(0).map(_=>Array(8).fill(false));

// fill square 3x1 at (2, 4)
for (var i = 0; i < 3; i++) {
  for (var j = 0; j < 1; j++) {
    multiArray[2 + i][4 + j] = true;
  }
}

document.getElementById("content").innerHTML = 
  multiArray.map(a => a.map(e => e ? 'X' : '0').join(''))
  .join('<br />');
<div id="content" />

Upvotes: 2

Related Questions