Confusion about double for loops execution

Tell us what’s happening:

Okay. So I’m using two for loops, the first to iterate over the top array, and the second to iterate over the inner arrays. I’m getting an error that are[i].length is not an object. I’m even getting a similar error for are[i][j]. Can anyone tell me where I’m going wrong?

Your code so far


function filteredArray(arr, elem) {
let newArr = [];
// change code below this line
for (let i = 0; i < arr.length; i++) {
  for (let j = 0; j < arr[i].length; j++) {
    if (arr[i][j] == elem) {
      arr.splice(i, 1);
    }
  }
}
// change code above this line
return newArr;
}

// change code here to test different cases:
console.log(filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3));

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.5 Safari/605.1.15.

Challenge: Iterate Through All an Array’s Items Using For Loops

Link to the challenge:
https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/basic-data-structures/iterate-through-all-an-arrays-items-using-for-loops

You’re destroying the array as you loop through it, so the length that goes into the loop is larger than the length of the array at the point those errors occur (null does not have a length, which is why you get an error)

Think about why newArr is declared (& is the return value) and how you would use it.

I think I get it. So basically I make newArr a copy of arr and have to iterate through arr, but destroy newer along the way, so that my loops stay unaffected. I tried something along those lines, but now I’m getting an error that says unexpected end of input. :\

Take a look at my code :

> function filteredArray(arr, elem) {
>   let newArr = [...arr];
>   // change code below this line
>   for (let i = 0; i < arr.length; i++) {
>     for (let j = 0; j < arr[i].length; j++) {
>       if (arr[i][j] == elem) {
>         newArr.splice(i, 1);
>       }
>     }
>   // change code above this line
>   console.log(newArr);
> }
> 
> // change code here to test different cases:
> filteredArray([[3, 2, 3], [1, 6, 3], [3, 13, 26], [19, 3, 9]], 3);

The error I’m getting is this :

unknown: Unexpected token

and the ending semi-colon is red-underlined. I debugged it for any syntax errors but I don’t know what I’m missing. :\

You’re missing the closing bracket for the outer loop, that’s the syntax error. You’re also not returning anything.

But you’re still destroying the array. Using splice (or any method that mutates) whilst iterating over an array is generally a Very Bad Idea

To illustrate why, the length that goes in to the outer loop in that example call is 4. But you’re deleting entries, so as the loop progresses you get to a point where you’re accessing indices that don’t have any value any more, because you’ve destroyed them

  • You don’t need to copy arr
  • You don’t need to modify arr
  • The end result should be an array containing the subarrays that passed the test.
1 Like

you have 4 opening curly braces, and only 3 closing ones - you are missing one

note that now the length stay constant, true, but the loop is still not checking stuff

[
   [3, 2, 3],    // index 0, first array
   [1, 6, 3],    // index 1, second array
   [3, 13, 26],  // index 2, third array
   [19, 3, 9]    // index 3, fourth array
]

first, array at inex 0 is checked
so inside it you have [3, 2, 3] - when i is 0 and j is 0 arr[i][j] is equal to elem
so, newArr.splice(0, 1) is executed, i is still 0, j is 1
newArr is

[
   [1, 6, 3],    // index 0, second array
   [3, 13, 26],  // index 1, third array
   [19, 3, 9]    // index 2, fourth array
]

arr[0][1] is 2, newArr[0][1] is now 6
no 3 here, let’s go forward. i is 0, j is 2. arr[0][2] is a 3
so newArr[0] is removed
noew newArr is:

[
   [3, 13, 26],  // index 0, third array
   [19, 3, 9]    // index 1, fourth array
]

now i is 1, j is 0. arr[1][0] is not 3
i is 1, j is 1, arr[1][1] is not a 3
i is 1, j is 2, arr[1][2] is a 3 so newArr[1] is removed

now newArr is

[
   [19, 3, 9]    // index 0, fourth array
]

now i is 2, j is 0
the thing is, that even if there is other stuff to remove in arr, there is nothing at index 2 or 3 in newArr now, so whatever you would do, it doesn’t work as you want

tl;dr
Don’t use splice inside a loop

1 Like

Thank you guys for taking out time to explain! I understood why the splice technique wasn’t working out. So I ended up setting a simple variable which is by default 1. If the iteration over an inner array encounters elem, the variable would switch to 0 and the loop over the current inner array would break, and would take on the next inner array. If it stayed 1 by the end of an iteration, the inner array would get pushed into newArr.

1 Like