How conditional "return" works for .filter() method?

Hello,

I am having confusion for how to have “return” work for .filter().

In this challenge: “Intermediate Algorithm Scripting: Missing letters”.

I first have tried my codes like this:

function fearNotLetter(str) {
  
  let all = "abcdefghijklmnopqrstuvwxyz";

  // find the correct consecutive string corresponding to str
  let compare = all.slice(all.indexOf(str[0]), all.indexOf(str[0]) + str.length);

  return compare.split("").filter(function (v) {
    if (!str.split("").includes(v)) {
      return v; 
    }
    return undefined;
    })
    .join("");
}

The codes above(1st) does not work as I expected…
Instead of returning the letter missing, it just returns string “compare”.
I am not sure exactly why… any idea please?

And then secondly I moved the function out of .filter() like below:

function fearNotLetter(str) {

  let all = "abcdefghijklmnopqrstuvwxyz";
  
  let compare = all.slice(all.indexOf(str[0]), all.indexOf(str[0]) + str.length);

  function findit(letter) {
    if (!str.split("").includes(letter)) {
      return letter;
    }
    return undefined;
  }

  return compare.split("").filter(findit).join("");
}

The codes above(2nd) works on all the cases except the last case that should return undefined:

fearNotLetter("abcdefghijklmnopqrstuvwxyz") should return undefined.

Any thought please?

Lastly, I tried ES6 arrow function like this:

function fearNotLetter(str) {
  
  let all = "abcdefghijklmnopqrstuvwxyz";
  
  let compare = all.slice(all.indexOf(str[0]), all.indexOf(str[0]) + str.length);

  return compare.split("").filter(v => 
  !str.split("").includes(v)).join("");
}

The codes above(3rd) works for all cases except the last one again, since I don’t know where and how I should put “return undefined” with ES6 arrow function like above…

Any thoughts what is the correct way to rewrite my codes to work as expected for 3 different styles above?

Thank you.

Filter works by going over the array and running the passed in function on every element and if that function returns truthy value the element is added to newly returned array.

In your first example you have a string "undefined" which is truthy and therefore that filter function will just be creating a copy of compare.

In second and third examples you finally do filtering, but filter returns an array, so even if the array is empty you’re running join on it and therefore returning an empty string instead of undefined.

Thank you for answering.
In the 1st case, it should be “return undefined” rather than “return “undefined””, it was a typo when posting it here. But why it still does not work with “return undefined”?
In the 2nd cases, shouldn’t it return undefined instead of empty when it did not meet the condition to go through “if” section?
For 3rd case, where and how should I put "return undefined’?

filter doesn’t care about exact value you return, it only cares about value being truthy of falsy.

For example, what would be the result of this?:

[0, 2, 0, 2, 6, 0].filter(() =>  0)

And this?:

[0, 2, 0, 2, 6, 0].filter(() =>  2)

Think about it then copy/paste into browser console to see the answer.

1 Like

Thank you. This two are great examples to help have a better understanding of .filter().
The first one returns empty array since “0” will be considered Boolean(0), which is false for each element and therefore it returns empty array.
The 2nd one returns all array since “2” will be considered Boolean(2), which is true for each element and therefore it returns all array.
Am I correct?

so there is no way we can put “return undefined” with .filter() for another condition like this?

Yes.

No. Filter will just skip the element if it sees undefined.

But think about your solution: in the last step you are doing join. Why?

Thank you for clarifying this! Otherwise, I would keep digging into how to make “return undefined” work with .filter().

Because the outcome from .filter() is in an array type, such as [‘d’] and the challenge is asking "d’, which is in a string type of data, so that’s why I used .join() to convert the outcome from an array to string.

According to challenge requirements there will be either one missing letter or no missing letters at all. So you’ll have an array with either one element or no elements at all. What happens if you try to access element at index 0 of an empty array?

1 Like

It is a good question. I was guessing null, empty or undefined, and it turns out it returns “undefined”.

var list =[];
console.log(list[0]); // this returns undefined

But back to this challenge, if I removed .join() like this, it just returns an empty array:

function fearNotLetter(str) {
 
  let all = "abcdefghijklmnopqrstuvwxyz";
  
  let compare = all.slice(all.indexOf(str[0]), all.indexOf(str[0]) + str.length);

  return compare.split("").filter(v => 
  !str.split("").includes(v));
}
console.log(fearNotLetter("abcdefghijklmnopqrstuvwxyz")) // this returns []
1 Like

Don’t return the array. Return the first element of final array.

1 Like

Ah I finally understood what you are talking about! Sorry I am so slow!

It’s brilliant! In this way, I don’t even need to dig into how to add “return undefined”.

Yes! By accessing index[0] of filtered array makes it work!!

function fearNotLetter(str) {
 
  let all = "abcdefghijklmnopqrstuvwxyz";
  
  let compare = all.slice(all.indexOf(str[0]), all.indexOf(str[0]) + str.length);

  return compare.split("").filter(v => 
  !str.split("").includes(v))[0];  // this would return undefined automatically for the last case
}

Thank you! You are so smart! :slight_smile: