cjhahaha
cjhahaha

Reputation: 33

Node.js: Multidimension Array Assignment

I want to use a 3x3 two-dimensional array to store data. However, when I assign 1 to g[1][1], I found the output strange - the whole second col was assigned to 1!

let g = new Array(3).fill( // 3 x 3
        new Array(3).fill(0)
    );

console.log(g);

g[1][1] = 1;

console.log(g);

this code outputs:

[ [ 0, 0, 0 ], [ 0, 0, 0 ], [ 0, 0, 0 ] ]
[ [ 0, 1, 0 ], [ 0, 1, 0 ], [ 0, 1, 0 ] ]

I upgraded my node to v9.11.1, and this issue remain unsolved. My system is MacOS High Sierra 10.13.6.

I want to ask:

  1. What is the right way to create and initiate a multidimension array?
  2. What is the right way to assign values to multidimension array elements?

Thanks.

Upvotes: 3

Views: 65

Answers (4)

zero298
zero298

Reputation: 26878

You are giving a reference to an object. Per the MDN documentation:

When the fill method gets passed an object, it will copy the reference and fill the array with references to that object.

const foo = new Array(3).fill(0);
let g = new Array(3).fill(foo);

console.log(JSON.stringify(g, null, 4));
foo[1] = 1; //g[1][1] = 1;
console.log(JSON.stringify(g, null, 4));

You won't be able to populate your array the way you want with fill, you'll have to break it out into 2 steps.

function cloneFill(arr, val, start = 0, end = arr.length) {
  for (let i = start; i < end; i++) {
    arr[i] = val.slice(0);
  }
}

const foo = new Array(3).fill(0);
let g = new Array(3);
cloneFill(g, foo);

console.log(JSON.stringify(g, null, 4));
g[1][1] = 1;
console.log(JSON.stringify(g, null, 4));

Upvotes: 0

Bucket
Bucket

Reputation: 7521

let g = new Array(3);

This is fine. Not the best practice, but it works. You have an array that has 3 empty entries. If you did

g.fill("foo");

You would get ["foo", "foo", "foo"]. Also seemingly fine. But instead you're creating a new object:

g.fill(new Array(3));

You'd think that new Array(3) would be called three times, but it is not. Instead, it is created once and then applied to each entry in the array. So at each index in g is pointing to the exact same object. Changing a property of that object will be reflected at each index in g because of this.

It's better practice to simply use loops to instantiate an nth-degree array, or to explicitly instantiate them:

let g = [];
for(var i = 0; i < 3; i++) {
    g[i] = [0, 0, 0];
}

Or:

let g = [[0, 0, 0], [0, 0, 0], [0, 0, 0]];

Upvotes: 0

Jonathan
Jonathan

Reputation: 167

Looks to me like you're putting the same array in all three spots of the outermost array. Try using a loop to make a new array for each row.

let size = 3;
let g = new Array(size);
for (var i = 0; i < size; i++) {
    g[i] = new Array(size).fill(0);
}

Upvotes: 1

Alexander Nied
Alexander Nied

Reputation: 13623

The problem is that you are filling your first array with three references of the same inner array. As such, when you mutate any instance it will be reflected across every entry in the outer array, because all three of it's items are just the same array. You might be better off doing this with loops if you want it to scale nicely:

function createMultidimensionalArray(size) {
    
    const outer = [];
    for (let i=0; i<size; i++) {
        outer.push(new Array(size).fill(0));
    }
    return outer;

}

let arr = createMultidimensionalArray(3);

console.log(arr);

arr[1][1] = "test";

console.log(arr);

Upvotes: 1

Related Questions