I was doing some training tasks for my JS course and I got one where you must implement a function that takes a positive integer (n) and returns a matrix like the one below (5 was passed):
[ [ 1, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 0 ],
[ 0, 0, 1, 0, 0 ],
[ 0, 0, 0, 1, 0 ],
[ 0, 0, 0, 0, 1 ] ]
I was able to implement the function with the following code:
function getIdentityMatrix(n) {
const mat = new Array(n).fill([]);
return mat.map((row, index) => {
row = new Array(n).fill(0);
row[index] = 1;
return row;
});
}
But while doing it I found a strange behavior that I can't explain... If I alter the code a little:
function getIdentityMatrix(n) {
const mat = new Array(n).fill(new Array(n).fill(0));
return mat.map((row, index) => {
row[index] = 1;
return row;
});
}
It returns a matrix like this:
[ [ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ] ]
Why would it work that way? It's like the forEach function iterates over all the elements nested inside each row which it shouldn't do.
Thank you for any advise!
It's because Array is a reference type. When you do
new Array(n).fill(new Array(n).fill(0))
first the inner
new Array(n).fill(0)
makes an array size n filled with0
; next the outerArray(n).fill
creates an array filled with n references to that inner array.It doesn't create n inner arrays, just n references to the same array. So when you change an element of that inner array, all the references in the outer array will reflect the change since they all point to the same object.
there is only 1 nested array, not n times array.
The code in question is equivalent to this:
Because you are using
fill
you are basically filling thatmat
array with references to theinnerArr
(which you can see clearly from the above console output)
.Then you do
row[index] = 1
for each i which is changing the same values (at i index) of the same array.Now your working example ... which could be written in a shorter form as:
Clearly
maps
over a newly created and thenspreaded
array ofn
but then overwrites each element with an entirely new array reference.Since that reference is brand new modifying it with
row[index] = 1
produces the expected behavior when wereturn the x
from the map.Another way to achieve this in one line is via
map
, Object.assign and Object.values like this: