1

I was just trying stuff out in Vanilla JS and ran into a problem where array.push does not push another array (row) whose elems got changed in a for loop, but rather replaces the whole array (mainArr). It would be better to show the code so please scroll below

function genArray(m, n) {
  let mainArr = [];
  let row = [];
  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
        row.push(j);
    }
    mainArr.push(row)
  }
  return mainArr;
}
let myArr = genArray(3, 2);
console.log(myArr);
/**
 * outputs:
 * 
 * [ [ 0, 1, 0, 1, 0, 1 ],
 *   [ 0, 1, 0, 1, 0, 1 ],
 *   [ 0, 1, 0, 1, 0, 1 ] ]
 * 
 * why not:
 * 
 * [ [ 0, 1 ], 
 *   [ 0, 1, 0, 1 ], 
 *   [ 0, 1, 0, 1, 0, 1 ] ]
 */

At first I thought it was just because of the reference being appended as this SOF answers says, but as the code shows it doesn't.

let arr1 = []
let arr2 = [1, 2]
arr1.push(arr2)
console.log(arr1); // [ [ 1, 2 ] ]
arr2 = [2, 4]
console.log(arr1); // still [ [ 1, 2 ] ]

let arr3 = []
let obj1 = {name: "John"}
arr3.push(obj1)
console.log(arr3); // [ {name: "John"}]
obj1.name = "Mike"
console.log(arr3); // [ {name: "Mike"} ]
Nugget
  • 81
  • 1
  • 6
  • 23

2 Answers2

1

You are updating the same array every time, so all inserted lists will eventually point to the same reference with the value set in the last iteration.

The following is a fix with an enhancement to reach the expected output:

function genArray(m, n) {
  const mainArr = [];
  for (let i = 0; i < m; i++) {
    const row = [];
    let count = i;
    while(count-- >= 0) {
      for (let j = 0; j < n; j++) {
        row.push(j);
      }
    }
    mainArr.push(row)
  }
  return mainArr;
}

console.log( genArray(3, 2) );
Majed Badawi
  • 27,616
  • 4
  • 25
  • 48
  • 1
    That made sense! I was thinking for over an hour why it behaves like that before asking and realizing that it was in fact because of the reference. Also in my second snippet, I realized that `arr2 = [3, 4]` doesn't change arr1 but `arr2.push(3, 4)` changes by appending. Thanks for the code and answer! – Nugget Jul 03 '22 at 18:56
1

You can use Destructuring assignment instead of array.push. just like this:

  function genArray(m, n) {
    let mainArr = [];
    let row = [];
    for (let i = 0; i < m; i++) {
      for (let j = 0; j < n; j++) {
        row=[...row,j];
      }
      mainArr.push(row)
    }
    return mainArr;
  }
  let myArr = genArray(3, 2);
  console.log(myArr);