Falsy Bouncer - JavaScript

I can’t figure out why my code does not work. It is removing the empty quotes but not the false element. This is in the Basic Algorithm Scripting module. Here is my code:

function bouncer(arr) {

  for (var i = 0; i < arr.length; i++) {

    if (arr[i] === false || arr[i] === null || arr[i] === 0 || arr[i] === undefined || arr[i] === NaN || arr[i] === "") {

      console.log(arr[i]);

      arr.splice(i, 1);

    }

  }

     

  return arr;

}

bouncer([7, "ate", "", false, 9]);

Thanks for the help.

I’ve edited your post for readability. When you enter a code block into a forum post, please precede it with a separate line of three backticks and follow it with a separate line of three backticks to make it easier to read.

Please use the “preformatted text” tool in the editor (</>) to add backticks around text.

See this post to find the backtick on your keyboard.
Note: Backticks are not single quotes.

markdown_Forums

You are making a reinvent-the-wheel error that many people do when it comes to the Falsy Bouncer. Here is a good explanation from @ArielLeslie :

Sorry @JeremyLT but I don’t understand your reply and the image(s) you attempted to attach are not displaying properly on my end.

Even if I’m “reinventing the wheel”, @JeremyLT, can you explain why my code doesn’t work? Thank you.

Did you look a the post I linked?

You have two problems

  1. Your checking for a hard-coded list of ‘falsy’ values is fragile and won’t work well
  2. You are mutating the array as you iterate over it, which is bug prone

Yes but that “post” appears to be a discussion for which there is no resolution until someone posted a solution at the end. I’m interested in understanding why my code isn’t working, not what version of correct code someone else used. Thank you.

Like I said

  1. Checking against a hard coded list of falsy values is fragile. You can’t really create a reliable comprehensive list of every falsy thing.
let myArr = [2, 0, "", null, "fluffy bunny"];

// Log if truthy
for (let i = 0; i < myArr.length; i++) {
  if (myArr[i]) {
    console.log(myArr[i]);
  }
}
  1. You are mutating the array as you iterate over it, which is bug prone. You get counterintutitive results as you iterate.
let myArr = [1, 2, 3, 4, 5];

for (let i = 0; i < myArr.length; i++) {
  myArr.splice(i, 1);
}

console.log(myArr);
  1. I’m guessing that part of the problem is I’m a beginner and this lesson is the first time I recall the word “falsy” being used. However, it’s defined right in the lesson as 1 of 6 posible things. My code is meant to test whether each array element is one of the 6. If it is, the splice action should remove it from the array. Not really sure what you mean by fragile here but even if the provided definition is not complete (and thus, not accurate), that wouldn’t explain why “false” is not removed by my code.

  2. Again, just because a certain method is “bug-prone,” doesn’t mean it actually has a bug in it. If there is one, I’m asking for someone to explain it to me. That’s literally the point of my post.

I know there may be a more elegant solution but inelegant solutions still work. I’m trying to figure out why mine doesn’t.

Thank you.

Did you try to run the code snippets I provided? The second snippit shows you that your mutating the array with splice as you iterate over the array is buggy.

The definition of falsy is not [false, null, 0, undefined, NaN, ""]. The definition of falsy is ‘a value that fails a logical conditional’

if (thisValueIsTruthy) {
  console.log("This variable was truthy!")
}

if (!thisValueIsFalsy) {
  console.log("This variable was falsy!")
}

@JeremyLT thank you for taking the time to respond here but I think you are simply misunderstanding my request. Thanks again.

I am understanding your request. You want to know why your code doesn’t work.

There are two reasons, as I have given. Both are important issues.

Splicing as you iterate just won’t work the way you want it to:

Your treatment of falsy values missed the idea behind the lesson (it is a tricky one!):

As Jeremy has said, you have 2 major problems with your code.

    if (arr[i] === false || arr[i] === null || arr[i] === 0 || arr[i] === undefined || arr[i] === NaN || arr[i] === "") {

This will not work. Specifically, arr[i]===NaN will not work (see here). It also misses the point of the lesson. The concept of values being “falsy” isn’t something made up by freeCodeCamp for the purposes of this challenge, but rather a quality that values have in programming languages. A value is falsy if the language treats the value as false when it is evaluated as a boolean. This means that Boolean(someFalsyValue) is false but also that we can use it in a conditional like if (someFalsyValue). We can also talk about values being “truthy”. As I’m sure you’ve guessed, truthy values evaluate to true in a boolean of logical context.

if (someFalsyValue) {
    // this code block is not entered
}
else if (someTruthyValue) {
    // this code block is entered and executed
}

The other major problem that your solution has is that you are removing items from the array inside a for loop. Your for loop works based on array index and array length, but if you remove items from your array then both the indices and the length are changing. Jeremy has given you several pieces of code that you can run to see this happening in real time so that you can see why your code doesn’t work.

1 Like

@JeremyLT i again thank you for taking the time but you’re either wrong or not explaining it well enough (to this beginner).

Your first reason was that I can’t test for every possible falsy value. I countered by saying that, even if that’s true, I tested for all the relevant ones. Whether or not there’s a falsy value that exists that I didn’t test for is irrelevant as to whether my code should remove the values it actually tests for. You haven’t addressed this point.

Your second reason is to tell me I used a bug-prone solution. I asked you to point out the actual bug but you haven’t. You just keep repeating that there’s a better way to do this (which I’m not arguing). My point is to figure out the actual bug in my code that you are hypothetically referring to.

You are just repeating your philosophical argument by using differnet words - “both are important issues” or “just won’t work the way you want it to.” Fine, but please explain why specifically to my code.

The last thing you did was provide me with some code to use, which I already stated is not my request.

Honestly, @JeremyLT, I do appreciate your willingness to try to help but at this point, this is just a waste of time for you and me. I’m hoping someone else will help.

Thank you.

@ArielLeslie thank you for responding but I am a beginner so most of this and the link you posted went over my head. I do, however, understand what you mean by the array changing length as each item is removed creating problems and I suspect that is what JeremyLT was referring to when he said it was bug-prone and fragile (I wish he would have just explained the specifics like you did). I’ll revisit with this new understanding and see how far I get but I definitely don’t yet understand the first part of your reply. Thanks again.

Comments added to your code:

function bouncer(arr) {
  // ISSUE 1:
  // You cannot iterate over an array while splicing
  //   elements out in this way. The element indices
  //   and the length of the array keep changing every
  //   time you call splice().
  for (var i = 0; i < arr.length; i++) {
    // ISSUE 2:
    // This comparison
    //    1) Missed the point of the lesson
    //    2) Will not work, specifically in the case of NaN
    if (arr[i] === false || arr[i] === null || arr[i] === 0 || arr[i] === undefined || arr[i] === NaN || arr[i] === "") {
      console.log(arr[i]);
      // Again, you are changing the array, which breaks
      //   how you are iterating over the array.
      arr.splice(i, 1);
    }
  }
  return arr;
}

bouncer([7, "ate", "", false, 9]);

To see ISSUE 1, consider this minimal version of your code which demonstrates what the problem is:

// Initialize array
let arr = [7, "ate", "", false, 9];

// Loop over array
for (let i = 0; i < arr.length; i++) {
  if (i > 0) {
    console.log(i);
    arr.splice(i, 1);
  }
}

// Check result
console.log(arr);

[https://repl.it/repls/KlutzyDarkredRedundantcode#index.js]
The condition looks like it says ‘remove all elements with an index greater than 0’, but that is not at all what happened because the indexes and length of the array are changing because the array is being modified as you iterate.

To see ISSUE 2, consider this minimal version of your code which demonstrates what the problem is:

// Initialize array
let arr = [NaN];

// Check for falsy
if (arr[0] === NaN) {
  console.log("Falsy");
}

[https://repl.it/repls/UnhealthyHauntingInterfacestandard#index.js]
Checking if a value matches a list of falsy values does not always work, as shown above.

Running and playing with the chunks of code I provided in the FCC editor or in the repl.it links I provided will help you understand the issues better.

You can’t compare to NaN it won’t work the link explains why.

Don’t compare to every falsy value. It’s not the point. Falsy values already are treated as false without comparing them to anything.

1 Like

I don’t understand what this means. This lesson was the first time I recall hearing the term falsy. As previously stated, even though the link may explain why to a more knowledgeable person, I didn’t (and don’t) understand it. You telling me again to read it in order to understand it does not help me understand it. As stated above, I will revisit my code with the array length understanding and see how far I get. Thanks again for replying.

All falsy means is that a variable holding a falsy value will fail a conditional test, as described above.

and i tested that condition for each of the provided possible falsy values and directed an action if it was a falsy value. i understand why the array length is a problem but not the test.