Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the value in a matrix after fill() returns incorrect matrix [duplicate]

Tags:

javascript

If I initialize the matrix like

x = [["O", "O", "O"], ["O", "O", "O"], ["O", "O", "O"]];

And then set x[0][1] = "X" It returns

[ [ 'O', 'X', 'O' ], [ 'O', 'O', 'O' ], [ 'O', 'O', 'O' ] ]

as expected

However, if I initialize the matrix as the following:

x = new Array(3).fill(new Array(3).fill('O'))

And then x[0][1] = "X" It gives me back

[ [ 'O', 'X', 'O' ], [ 'O', 'X', 'O' ], [ 'O', 'X', 'O' ] ]

What is going on here?

like image 424
whatever123 Avatar asked Jan 26 '23 22:01

whatever123


1 Answers

When you do this:

x = [["O", "O", "O"], ["O", "O", "O"], ["O", "O", "O"]];

Javascript is creating 3 different Arrays in memory, so when you access x[0][1] you're accessing just that array.

When you are using the:

x = new Array(3).fill(new Array(3).fill('O'))

You are basically filling the array with same array 3 times, so when you access x[0][1] you're accessing the same Array in memory that's also connected to x[1] and x[2].

As commented by @Shidersz, a possible iterative solution would be:

// one liner:
Array.from({length: 3}, x => new Array(3).fill("0"));

This is creates an array and populates it with the values returned from the inputed function. Here's a breakdown:

// same as previous only longer with comments
// Create an Array from the first argument,
//as modified by the mapping function in the 2nd argument
Array.from(
  // This could be any array like object. 
  // In the case of length it just reads the length property
  // and iterates that number of times,
  // so it could be useful if you want to 
  // fill the top array with 100000 arrays.
  {length: 3},
  // x argument for the mapping is irrelevant
  x => {
    // returning the array with 3 "0" strings in it.
    return  new Array(3).fill("0")
  });

docs here for more reference.

like image 65
aviya.developer Avatar answered May 19 '23 04:05

aviya.developer