This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 2 years ago.
The code I'm working on right now requires me to assign a value to a single cell in a 2-D array.
But the assignment doesn't seem to work out as expected.
let b = new Array(3).fill(new Array(3).fill(0));
b[1][1] = 1;
console.log(b.toString());
I just can't really understand why it produces this output.
The below code gives me the output I expect but I would really prefer being able to do it in a manner that resembles the first snippet.
let b = []
for(let i = 0; i < 3; i++){
b.push([])
for(let j = 0; j < 3; j++){
b[i].push(0)
}
}
b[1][1] = 1
console.log(b.toString())
You can avoid assigning the same array reference by using the built in mapping callback of Array.from()
let b = Array.from({length:3}, (_,i) => Array(3).fill(i));
console.log(b)
In your first example, it creates one array, then fills every element to that one array. This means that a change in one will be reflected in everything else. If you want to construct a new array for each element, then you could try mapping it:
let b = new Array(3).fill(null).map(_ => new Array(3).fill(0));
b[1][1] = 1;
console.log(b.toString());
Related
This question already has answers here:
How to use a variable for a key in a JavaScript object literal?
(16 answers)
Is it possible to add dynamically named properties to JavaScript object?
(20 answers)
Closed 2 years ago.
I'm trying to find out how to initialise an array of objects, where each object has the index (i) as its key and 0 as its value. The code below is not working as expected but I can't see why. I'm still quite beginner with Javascript and couldn't find an answer elsewhere.
var n = 10;
var sample = [];
for (var i = 0; i < n; i++)
sample.push({i : 0});
you should use this syntax sample.push({[i]: 0});
when you need to access object property which is stored under some variable you should always use square brackets no matter you need write to or read from an object
The code below should take care of the job:
let n = 10;
let sample = Array.from({length:n}, (_, i) => ({ [i]: 0 }));
As pointed by Oleksandr Sakun on his answer, the index is used between brackets in order to evaluate the variable and set as a property of the object.
For a funcitonal approach you can try:
const initArray = (n)=>{
const newArr = new Array(n).fill(0);
return newArr.map((value, index)=> ({[index]: value}))
}
add square brackets to the index [i] :
var n = 10;
var sample = [];
for (var i = 0; i < n; i++)
sample.push({[i]: 0});
console.log(sample);
This question already has answers here:
new Array(_).fill(object) does not create new instances of object [duplicate]
(5 answers)
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Closed 2 years ago.
let's look at the code:
Test() {
let array1 = new Array(5).fill({ a: 0 })
let array2 = new Array(5).fill({ a: 0 })
for (let i = 0; i < 5; i++) {
setTimeout(() => {
array1[i].a = i
array2[i] = {a:i}
console.warn("array = ", array1)
console.warn("array2 = ", array2)
}, 0.2 * i)
}
}
In this case, I wanna assign a series of values to the array1 & array2, and there are two ways to do it, which lead to totally different results.
In the case array1[i].a = i, after all the code is ran, the result is array = [{a:4},{a:4},{a:4},{a:4},{a:4}], which is not what i wanted.
In the second case array2[i] = {a:i}, the result will be [{a:0},{a:1},{a:2},{a:3},{a:4}] as expected.
I wanna know why is it like this? What's the machanics behind this phenomenon?
Thank you.
When you call .fill() and pass an object, you assign the exact same object to every element of the array. Thus, modifying a property at one array index modifies the same property at all the other indexes, because they're all pointing to the same thing.
There are a variety of ways around this issue. You could fill the array with 0 or null or some dummy value and then iterate through with .forEach(), or more simply just use an indexed for loop to initialize each element. If you initialize with { a: 0} in a for loop, a new object will be created on each iteration.
This question already has answers here:
Array.prototype.fill() with object passes reference and not new instance
(7 answers)
Unexpected behavior using Array Map on an Array Initialized with Array Fill [duplicate]
(1 answer)
Closed 6 years ago.
I'm trying to create a 6 by 12 Matrix using Array.fill
let m = Array(6).fill(Array(12).fill(0));
While this works, the problem is that the inner Arrays are actually all referencing the same Array object.
let m = Array(6).fill(Array(12).fill(0));
m[0][0] = 1;
console.log(m[1][0]); // Outputs 1 instead of 0
I wanted (and expected) the value of m[1][0] to be 0.
How can I force Array.fill fill copy-by-values of the given argument (eg: Array(12).fill(0) is the argument in my case) instead of copying by reference ?
You could use Array.from() instead:
Thanks to Pranav C Balan in the comments for the suggestion on further improving this.
let m = Array.from({length: 6}, e => Array(12).fill(0));
m[0][0] = 1;
console.log(m[0][0]); // Expecting 1
console.log(m[0][1]); // Expecting 0
console.log(m[1][0]); // Expecting 0
Original Statement (Better optimized above):
let m = Array.from({length: 6}, e => Array.from({length: 12}, e => 0));
You can't do it with .fill(), but you can use .map():
let m = new Array(6).map(function() { return new Array(12); });
edit oh wait that won't work; .map() won't iterate through the uninitialized elements. You could fill it first:
let m = new Array(6).fill(null).map(function() { return new Array(12); });
You can't do it with Array#fill method. Instead iterate over the array and add newly created array using a for loop.
let m = Array(6);
for (var i = 0; i < m.length; i++)
m[i] = Array(12).fill(0)
m[0][0] = 1;
console.log(m[1][0]);
This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 4 years ago.
When i use Array.fill to fill a multidimensional array, i get a weird behaviour when pushing to one of the arrays:
var arr = Array(2).fill([]);
arr[0].push(5);
console.log(arr);
//=> prints [[5], [5]]
fill is essentially doing this:
var content = [];
for (var i = 0; i < 2; i += 1) {
arr[i] = content;
}
So, your array will have a reference to the array you've passed to fill in each property.
It sounds weird, but what your code actually does is create an array ([]) and put a reference for that array in each of the items of the Array(2). So whenever you change that reference - every array that is referenced to that Array is changed.
It's exactly the same as:
var a = [];
var arr = Array(2).fill(a);
a.push(5);
console.log(arr[0][0], arr[1][0]);
a[0] = 2;
console.log(arr[0][0], arr[1][0]);
You can see that the values inside the arr are affected by the change to the a array.
This question already has answers here:
Array.fill(Array) creates copies by references not by value [duplicate]
(3 answers)
Closed 4 years ago.
When i use Array.fill to fill a multidimensional array, i get a weird behaviour when pushing to one of the arrays:
var arr = Array(2).fill([]);
arr[0].push(5);
console.log(arr);
//=> prints [[5], [5]]
fill is essentially doing this:
var content = [];
for (var i = 0; i < 2; i += 1) {
arr[i] = content;
}
So, your array will have a reference to the array you've passed to fill in each property.
It sounds weird, but what your code actually does is create an array ([]) and put a reference for that array in each of the items of the Array(2). So whenever you change that reference - every array that is referenced to that Array is changed.
It's exactly the same as:
var a = [];
var arr = Array(2).fill(a);
a.push(5);
console.log(arr[0][0], arr[1][0]);
a[0] = 2;
console.log(arr[0][0], arr[1][0]);
You can see that the values inside the arr are affected by the change to the a array.