Falsy Bouncer - Basic Algorithm Scripting

Just wondering why my code doesn’t work.

Challenge is to remove any falsy values from an array. After peeping the hints I realize my solution is a little convoluted but I’m not sure why it doesn’t still work.

function bouncer(arr) {
let falsyArray = [false, null, 0, "", undefined, NaN];
for (let i = 0; i < arr.length; i++) {
  if (falsyArray.indexOf(arr[i]) >= 0) {
    arr.splice(i, 1);
  }
}
return arr;
}
bouncer([7, "ate", "", false, 9]);
//The output is [ 7, 'ate', false, 9 ]

I created an array, falsyArray of all the falsy values

I then iterate through each value of arr, checking whether each value corresponds to any of the falsy values stored in falsyArray - if there is a match, that value is removed from arr using splice()

It looks like it only finds the first match, in this case the empty string "", deletes that and returns.

I know indexOf() only finds the first match and returns, but I would have thought since it is utilized in the condition of an if statement nested within a for loop that the for loop would still iterate through each value of arr.

Is using indexOf() the reason the for loop stops iterating through arr after finding the first match?

  **Your browser information:**

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

Challenge: Falsy Bouncer

Link to the challenge:

Your problem is that indexOf() uses strict equality:

This doesn’t always work as you expect for some falsy values:

console.log(NaN === NaN);
1 Like

Ahh yeah, ofcourse - you know the index is the position of an element in the array? What happens, if you remove an element from the array? All numbers on the right are shifted one to the left. If you remove the element on index 2, what was index 3 is now index 2. But the for-loop doesn’t care, it’s just counting up. So after it counted 2, it counts 3 → resulting in one element getting skipped.
In your case: it removed "" on index 2, causing false from index3 to now be index 2 but the loop goes to check index 3 next, which is now 9 and not the new value on index 2.

Easiest way to fix it and a recommended approach to most issues in general is to seperate variables for input and output. Meaning instead of removing elements from arr, you instead add elements to a newly created arr2.
There are a couple of reasons for doing this - most notably it’s easier to follow what the code is doing, if you don’t have to follow changes in important variables.

2 Likes

Ah, that’s a good problem with this approach too… Good catch!

Mutating incoming arrays and objects is usually just not the right approach. One hint comes in the form of the return statement from the function. The function takes something in, does something to it, and returns the newly transformed data back out. That is what a “true” function does.

If you only work with the data coming in and mutate it, then you have no real reason to return anything and you would just reference the outside data structure after mutating it. Such code is often called a subroutine, at least in some languages.

I would suggest you stick to functions taking in data and returning out new data, when possible without mutating reference objects.

3 Likes

That’s such a good perspective on functions that I wasn’t even considering! My tunnel vision was so focused on passing the challenges I was trying to destroy the input data just to get there

1 Like