Debugging - Use Caution When Reinitializing Variables Inside a Loop

Tell us what’s happening:
Describe your issue in detail here.

Your code so far
I have a semi-related question. I just need a little clarification as to why, when the row array is a global variable outside of the nested for loop, the newArray still has three indices once the function returns newArray? Shouldn’t the function return once i = 2???
That is, why isn’t newArray:
[0, 0, 1, 1, 2, 2]
This to me makes sense because i = 2 , and the function call should be done. The function returns newArray.

Instead, newArray is actually:
[ [0, 0, 1, 1, 2, 2],
[0, 0, 1, 1, 2, 2],
[0, 0, 1, 1, 2, 2] ]
Why does it reset and continue to add to newArray? Shouldn’t the function return once i = 2 the first time?

function zeroArray(m, n) {
  let newArray = [];
  let row = [];
  console.log("global variable")
  for (let i = 0; i < m; i++) {
    //let row = [];
    //console.log("reset local")
    for (let j = 0; j < n; j++) {
      row.push(i);
      console.log("j loop iteration i " + i);
    }
    newArray.push(row);
    console.log("push i loop " + i)
  }
  console.log("return newArray")
  return newArray;
}

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

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36

Challenge: Debugging - Use Caution When Reinitializing Variables Inside a Loop

Link to the challenge:

row is not global but within the function scope.
you need to reinitialize it within the (i) for-loop. but it should be declared outside the loop.
let row is a declaration
row=[ ] is initialization (to an empty array).

if my terminology is wrong i’m sure someone will correct me

but try logging row/array inside each loop with some identifier
(eg console.log('1:', row) ).

Thank you for clarifying the terminology. I am still confused though why
[0, 0, 1, 1, 2, 2] repeats? Shouldn’t the return happen at the end of that last number 2?

What do you think the output should be?

I’m obviously missing something, but in my mind since i is no longer less than m, then the array should stop at :
[0, 0, 1, 1, 2, 2]

I know I’m probably missing a fundamental idea when it comes to arrays and for loops. I am hung up on the idea that if the outer loop condition has failed why is there a second and even third iteration of “[0, 0, 1, 1, 2, 2]”?

But this line is called multiple times because it is inside of a loop.

Why has the outer condition failed? i < m is only false when i >= m. You need to make i bigger by 1 multiple times to make that happen.

i think you have multiple issues if i’ve understood.
first of all:
what does the challenge ask you to push/put into each element? rows and columns of …?
and what are you putting into the elements?
is it the same?

I think I can clarify my confusion after playing with the code some more. Your explanations make a lot of sense when the row variable is reset in the outer loop.

function zeroArray(m, n) {
  let newArray = [];
  //let row = [];
  //console.log("\"row\" outside of for loop")
  
  for (let i = 0; i < m; i++) {
    let row = [];
    console.log("reset local 'row'")
    for (let j = 0; j < n; j++) {
      row.push(i + "/" + j);
      console.log("i=" + i + ", j=" + j);
    }
    newArray.push(row); 
    console.log("push row ij combination \n")
  }
  console.log("return newArray")
  return newArray;
}

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

//output is: 
//reset local 'row'
//i=0, j=0
//i=0, j=1
//push row ij combination 
//
//reset local 'row'
//i=1, j=0
//i=1, j=1
//push row ij combination 
//
//reset local 'row'
//i=2, j=0
//i=2, j=1
//push row ij combination 
//
//return newArray
//[ [ '0/0', '0/1' ], [ '1/0', '1/1' ], [ '2/0', '2/1' ] ]

After this challenge, I will for sure never forget to re-initialize an array (in this case “row”). I guess my question is specifically: how does failing to reset the row variable result in what seems to be three instances of i = 0, i = 1, i = 2? Why does it cause this bug? Am I digging far too deep into this? Should I just pay attention to proper syntax and not worry about why this is a bug and how the output is the way it is?

function zeroArray(m, n) {
  let newArray = [];
  let row = [];
  console.log("\"row\" outside of for loop")
  
  for (let i = 0; i < m; i++) {
    //let row = [];
    //console.log("reset local 'row'")
    for (let j = 0; j < n; j++) {
      row.push(i + "/" + j);
      console.log("i=" + i + ", j=" + j);
    }
    newArray.push(row); 
    console.log("push row ij combination \n")
  }
  console.log("return newArray")
  return newArray;
}

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

//output: 
//"row" outside of for loop
//i=0, j=0
//i=0, j=1
//push row ij combination 
//
//i=1, j=0
//i=1, j=1
//push row ij combination 
//
//i=2, j=0
//i=2, j=1
//push row ij combination 
//
//return newArray
//[ [ '0/0', '0/1', '1/0', '1/1', '2/0', '2/1' ],
//  [ '0/0', '0/1', '1/0', '1/1', '2/0', '2/1' ],
//  [ '0/0', '0/1', '1/0', '1/1', '2/0', '2/1' ] ]

I understand the requirement of the challenge and proper syntax of the code. I think my question is really digging deeper as to why the original code in the challenge happens to log the array in such a buggy way. If that makes sense? The buggy array as a result of the challenge’s original code is what I’m trying to make sense of.

I wouldn’t say the array itself is ‘buggy’. It just isn’t doing what you expect.

What do you see here

function zeroArray(m, n) {
  let newArray = [];
  let row = [];
  console.log("global variable")
  for (let i = 0; i < m; i++) {
    //let row = [];
    //console.log("reset local")
    for (let j = 0; j < n; j++) {
      row.push(i);
      console.log("j loop iteration i " + i);
    }
    console.log("contents of row:", row);
    newArray.push(row);
    console.log("push i loop " + i);
    console.log("contents of newArray:", newArray);
  }
  console.log("return newArray")
  return newArray;
}

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

i would use a small simplification of jeremys example:

function zeroArray(m, n) {
  let newArray = [];

  for (let i = 0; i < m; i++) {
    let row = [];

    for (let j = 0; j < n; j++) {
      row.push(i);
      console.log('inner j:',j,'(outer)i:',i,'row:',row);
    }

    newArray.push(row);
    console.log('outer i:',i,'newArray:',newArray);
  }
  
  return newArray;
}

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

but the point is you can now play around with where you reinitialize a variable and see what’s actually happening.

1 Like

It might also be worth making it clear that it is a “reference” to the array that is pushed. With only one row array it is the reference being mutated.

function zeroArray(m, n) {
  let newArray = [];
  let row = [];
  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
      row.push(i);
    }
    newArray.push(row);
  }

  console.log(newArray);
  /* 
    [ [ 0, 0, 1, 1, 2, 2 ],
    [ 0, 0, 1, 1, 2, 2 ],
    [ 0, 0, 1, 1, 2, 2 ] ]
  */

  row[6] = 'This is added to every row';

  console.log(newArray);
  /*
    [ [ 0, 0, 1, 1, 2, 2, 'This is added to every row' ],
      [ 0, 0, 1, 1, 2, 2, 'This is added to every row' ],
      [ 0, 0, 1, 1, 2, 2, 'This is added to every row' ] ]
  */
  return newArray;
}

zeroArray(3, 2);

Unlike if you redeclared the array on every outer loop iteration, or re-initialize it to an empty array after each outer loop iteration. Then each iteration gets its own array.

I see iterations of row after each j loop. I also see iterations of newArray after each i loop.

Whenever row is updated with row.push(i) with a new index and value in the inner loop, newArray is updated with a new index and the value of whatever is in the row array.

And since row is never reset, it will hold all the values assigned to it from the very beginning.

Thank you for that walk through. I think it also helped me to walk away from the code for a while too. I appreciate you.

1 Like

Thank you, @ugwen , for sticking with me on this.

Thank you, @lasjorg ! That was going to be my next question, why the previous indexes of newArray ALSO update with the value of each new “row” iteration. Thank you for clarifying that it is a reference to the row array that is being pushed.

But why, when it is cleared after each iteration, does it not output [2,2] for each index of newArray if it is a reference to row?

To be clear, why not this?: [ [ 2, 2 ], [ 2, 2 ], [ 2, 2 ] ]
Rather, the output is: [ [ 0, 0 ], [ 1, 1 ], [ 2, 2 ] ]

I think I’ve read this somewhere and/or I am making the assumption based on deduction…is it because now that it is a local variable (to the loop) and no longer a (so to speak) global reference? Instead the new value after each iteration is being pushed?

function zeroArray(m, n) {
  let newArray = [];
  let row = [];
  for (let i = 0; i < m; i++) {
    for (let j = 0; j < n; j++) {
      row.push(i);
    }
    newArray.push(row);
    row = [];
  }

  return newArray;
}

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

This makes a brand new array to reference with row - it doesn’t ‘clear’ the old array, and it doesn’t change the reference stored in newArray.

1 Like