-1

Given a 3x3 matrix I want to set the element in the first row, 3rd column to true.

I would expect that m[0][2] = true would do it, but it does not. It sets the whole column to true!

My code to create the array and set the value is below. What caused this behavior?

const size = 3;

const m = Array(size).fill(Array(size).fill(false))

console.log(m); 
/* [[false, false, false], 
    [false, false, false], 
    [false, false, false]]
*/

m[0][2] = true;

console.log(m);
/*
   [[false, false, true], 
    [false, false, true], 
    [false, false, true]]
*/
Adrian
  • 9,102
  • 4
  • 40
  • 35
  • Does this answer your question? [Array.fill(Array) creates copies by references not by value](https://stackoverflow.com/questions/37949813/array-fillarray-creates-copies-by-references-not-by-value) – jonrsharpe Jun 19 '20 at 07:40
  • The behaviour you describe is already *telling* you that they're the same reference. That specific dupe suggestion is just one of many signposts around this behaviour with Array.fill - https://stackoverflow.com/q/27613126/3001761, https://stackoverflow.com/q/60432172/3001761, https://stackoverflow.com/q/57514341/3001761, ... – jonrsharpe Jun 19 '20 at 11:20

2 Answers2

3

You are filling the first array with the same array in every spot.

let array1 = [false, false, false];
let array2 = array1;
array1[2] = true;
console.log(array2);

Use Array.from

let size = 3;
let m = Array.from({ length: size }, _ => Array.from({ length: size }, _ => false));
console.log(m);
m[0][2] = true;
console.log(m);

This way you have a different instance of an array in each slot of the top level array.

You could use Array.fill in the function as false is a value object not a reference object.

let size = 3;
let m = Array.from({ length: size }, _ => Array(size).fill(false));
console.log(m);
m[0][2] = true;
console.log(m);
Adrian Brand
  • 20,384
  • 4
  • 39
  • 60
-1

7 Ways to create 2D matrices in JavaScript:

One liners:

const size = 3;
const val = null;

const m1 = Array(size).fill(Array(size).fill(val)); // issue: rows are all the same.
const m2 = Array(size).fill([...Array(size).fill(val)]); // issue: rows are the same;

const m3 = Array(size).fill().map(_ => Array(size).fill(val));
const m4 = Array.from(Array(size), _ => Array(size).fill(val));

const m5 = Array.from({length: size}, _ => Array.from({length: size}, _ => val))

All of these will create size x size matrices. However, using Array.fill directly will create copies by reference and not by value (e.g. m1 and m2). You can use Array.fill inside a mapper function to fix the issue (e.g. m3, m4, and m7). Finally, you can create matrices using Array.from twice.

There are 2 more ways of creating matrices but not as elegant.

Using for loops:

const m6 = [];
for(let i = 0; i < size; i++) {
    m6[i] = [];
    for(let j = 0; j < size; j++) {
        m6[i][j] = val;
    }
}

const m7 = Array(size);
for(let i = 0; i < m7.length; i++) {
    m7[i] = Array(size).fill(val);
}
Adrian
  • 9,102
  • 4
  • 40
  • 35