Explanation needed for "Use Caution When Reinitializing Variables Inside a Loop"

I’m having difficulty understanding the logic of this exercise and why we need to move the empty row array from outside the loop to inside the outer loop. I read draber06’s explanation, however it still doesn’t make complete sense to me. Here is what he wrote:

Problem is that row never resets. Arrays and objects act as pointers in JavaScript. When you push row into the matrix array, you are pushing a pointer to row into the matrix array, not a copy of row at that point in time. The next time you change row by pushing a 0 onto it, the row already in the matrix array changes too. That’s because matrix[0] is a pointer to a location in memory, and when you call row.push(0), you are changing that location in memory. Therefore the next time you call matrix[0] it will include all changes you’ve made.
You’ll find that matrix[0] === matrix[1]. Same is true for matrix[2]. They are all three pointers to the same location in memory (row).
To solve this, you want to put your row = [] inside the first for loop. This tells it to make a new row (or a new location in memory) every iteration.
If you want to get your expected outcome of 2 columns, 4 columns, 6 columns, then instead of pushing row to matrix, push row.slice(0). This pushes a copy of row to matrix, meaning that all subsequent changes to row will not affect the copy that you pushed. That is, matrix will not contain a pointer to row, but a pointer to a copy of row at some point in time.

I’d really appreciate if someone could break it down in somewhat different terms to make it more comprehensible to me, or link to an article somewhere that goes into this issue at a slower pace and in perhaps more detail.

This is quite an important topic because I know that later challenges in the intermediate algorithms section will make use of problems similar to this one.

1 Like

can you add a link to this exercise?

Which part of @draber06’s explanation do you not understand?

In the future, please post the url of the challenge, so other users do not have to search and find it.

https://learn.freecodecamp.org/javascript-algorithms-and-data-structures/debugging/use-caution-when-reinitializing-variables-inside-a-loop/

The entire explanation I found to be simply too confusing, even after reading it over many, many times.

That’s why I asked if someone could explain it in different terms, or in a different format, etc.

OK, I will try to explain why you must move the empty row array to be inside the outer loop.

You want the final array (newArray) to be an array of arrays. Not only that, but you want newArray to only contain m number of sub arrays which have a length of n.

If you leave leave the let row = [] outside the outer loop, then row keeps growing beyond the n number length each row array should have.

Sometimes it is best to see using console.log statements.

function zeroArray(m, n) {
  // Creates a 2-D array with m rows and n columns of zeroes
  let newArray = [];
  let row = [];
  for (let i = 0; i < m; i++) {
    console.log('i = ' + i);
    console.log('row starts as ' + JSON.stringify(row));
    // Adds the m-th row into newArray
    for (let j = 0; j < n; j++) {
      // Pushes n zeroes into the current row to create the columns
      row.push(0);
    }
   console.log('after pushing values to row, row is ' +  JSON.stringify(row));
    // Pushes the current row, which now has n zeroes in it, to the array
    newArray.push(row);
  }
  return newArray;
}

let matrix = zeroArray(3, 2);
console.log(matrix);

Running the above code, produces the following in the browser’s console.

i = 0
row starts as []
after pushing values to row, row is [0,0]
i = 1
row starts as [0,0]
after pushing values to row, row is [0,0,0,0]
i = 2
row starts as [0,0,0,0]
after pushing values to row, row is [0,0,0,0,0,0]
[ [ 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0 ],
[ 0, 0, 0, 0, 0, 0 ] ]

If you move the empty array declaration inside the outer for loop, the console would look like:

i = 0
row starts as []
after pushing values to row, row is [0,0]
i = 1
row starts as []
after pushing values to row, row is [0,0]
i = 2
row starts as []
after pushing values to row, row is [0,0]
[ [ 0, 0 ], [ 0, 0 ], [ 0, 0 ] ]

4 Likes

Thanks, that made it a little bit clearer.

u got it wrong bud. the above code should be:
[

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

]

1 Like

No, they are right - check what happens with a tool like this:

http://pythontutor.com/javascript.html

I just analysed the entire process using python tutor and it looks like it went through this 6 times:

for (let j = 0; j < n; j++) {
      
  
      row.push(0);
    }

to produce 6 zeroes. this is mind boggling…im pretty sure it goes through only 2 times because j = 0 and j= 1 is less than 2. once it becomes 2, it wont execute the 3rd time. why? ieah? look at the i condition. it stopped running once it reached 3. can you please explain? im baffled.

1 Like

There is an outer loop too

does j resets to 0 after becoming 2 and failing the condition? that MUST BE THE ONLY ANSWER. please answer!!!

what do u mean by outer loop? the loop carrying the i variable? if ur talking about that, then yeah i get that. i get the whole process. but my only problem is, if j resets to 0 after failing the condition and going back to i condition to re-run everything again.

i= 0 produces [0,0]
i = 1 produces [0,0]
i = 2 produces [0,0]

together [0,0],[0,0],[0,0] which were all pushed to an empty array called newArray
so answer >> [ [0,0],[0,0],[0,0] ]

but for this to be possible, j has to reset to 0 every time we fail its condition and iterate i again from the top.

You are confused about why it is not like the above, but it has six zeroes in all the subarrays when there is not row = [] inside the loop, right?

1 Like

no the above has nothing to do with what im saying. actually the top is gibberish. it was my analysis before using the pythontutor that u gave to me to use. let me re-write another comment and make it clean

When a loop start the first thing that happen is the initialisation of the variable (for (let k = 0; ...), so yeah, when the loop with the j variable starts the j is set to 0 (you can use the tool to see when it happens)

yeah j is set to 0 from the START. but i seen the python tutor. it showed much more than that.

j = 0 >>> push 0 to array: [0]
j = 1 >>> push 0 to array : [0,0]
j = 2 > fails condition/ no execution of its statements

so push [0,0] to newArray, another empty array to form this [ [0,0] ]

so now obviously we need 2 more sub arrays of THIS [0,0] to make it [ [0,0],[0,0],[0,0] ]. correct?

but we do realize J =2 NOW. meaning it would fail its condition and not execute again. meaning, it shouldn’t push any more 0s. so im asking if j is reset to 0 to produce the 2 more sub arrays we want?

But at that point, the i loop do an other iteration (i passes from 0 to 1) and everything inside the outer loop is executed again, so the let j = 0 is executed again

so when i increments 1. j = 2 before becomes j =0 again to let whatever inside the outer loop execute again/ push 0s again?

It’s more like they are two different loops

When a loop start the first thing is the initialisation of the variable.

j is not reset to 0, an other j is initialised to 0

1 Like

but how does that work though? there’s only 1 inner loop holding a j. meaning there’s only 1 j loop.

for (let j = 0; j < n; j++) {
      
  
      row.push(0);
    }
    
    newArray.push(row);
     row = [];
  }