Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do changes made to a cell propagate to other cells in this 2 dimensional array created using fill?

I have a problem with this 2-dimensional array in JS. When I change a[1][0], a[0][0] changes with it. Is there something wrong in the way I am initializing it? If yes, how can I initialize it properly?

>var a = Array(100).fill(Array(100).fill(false));
>a[0][0]
>false
>a[1][0]
>false
>a[1][0] = true
>true
>a[1][0]
>true
>a[0][0]
>true
like image 777
Hao Avatar asked Jul 07 '17 05:07

Hao


2 Answers

var a = Array(100).fill(Array(100).fill(false));

a contains an array, each element of which references to an array. you are filling the outer array with an array which contains all false values. The inner array is being made only once and reference to the same array is passed to each element of outer array that is why if you perform an operation on one element it reflects on other elements as well.

This is actually equivalent to

var a1 = Array(100).fill(false);
var a = Array(100).fill(a1);

here a gets 100 elements all having reference to same array a1. So if you change one element of a, all elements change since they are references to same array.

you will need to fill each element in outer array with a new array. you can do something like this:

var a = [];
for(var i=0; i<100; i++)
  a.push(Array(100).fill(false));
like image 122
Dij Avatar answered Oct 06 '22 08:10

Dij


Your entire array will be filled with references to the same (second dimension) array object.

To fill it with distinct objects, you'd have to do something like this:

const a = Array(100).fill(false).map(x => Array(100).fill(false));

a[0][0] = true;

console.log(a[0][0]);
console.log(a[0][1]);
console.log(a[1][1]);

Note that the values in the initial array need to be explicitly set to something (in my example false, but could also be undefined), because the array created by the constructor is sparse and the map() function will only operate on properties that actually exist.

To work around that, you could use Array.from():

const a = Array.from(Array(100), x => Array(100).fill(false));

a[0][0] = true;

console.log(a[0][0]);
console.log(a[0][1]);
console.log(a[1][1]);
like image 23
Robby Cornelissen Avatar answered Oct 06 '22 07:10

Robby Cornelissen