Both the solutions to this lesson are wrong - JavaScript

Implement the filter Method on a Prototype

Tried to run both these since I was stuck and they both return the wrong output. Check it out for yourself. The lesson is here.

Anyone with answers?

!!{} will be true. But based on your condition,
({}) == true will equate to false

The callback values should not be checked against true

if (callback(x)) {
      newArray.push(x);
 }

Solution 1 : Solve this challenge using recursion

Array.prototype.myFilter = function(callback, arr = [], i = 0){
  if(i < this.length){
    if(callback(this[i])){
      arr.push(this[i])
    }
    return this.myFilter(callback,arr, i+1)
  }else{
    return arr
  }
}

Solution 2 : Solve this challenge using foreach

Array.prototype.myFilter = function(callback){
  this.forEach(item => {
    callback(item) && newArray.push(item)
  })
}
3 Likes

Considering that the lesson “Implement map on a prototype” is provided with a solution that use recursion and since I suck at recursion I wanted to do this one with recursion as it was very similar.

This is very similar to alaa-essaies solution but use ternary operator instead of “if statemenet” and it explain to beginners the difference using of post increment and pre increment:

// the global Array
var s = [23, 65, 98, 5];
Array.prototype.myFilter = function(callback,newArr=[],i=0){
  //console.log(i) //This is used to keep track of "i" value during execution for the tricky explanation.
  return i>=this.length 
        ? newArr
        : callback(this[i])
        ? this.myFilter(callback,newArr.concat(this[i]),++i)
        : this.myFilter(callback,newArr,++i)

};

var new_s = s.myFilter(function(item){
  return item % 2 === 1;
});

console.log(new_s); //print [23,65,5]

As you can see here

Array.prototype.myFilter = function(callback,newArr=,i=0)

, we pass the callback function, a newArr as Array that will get populate and returned as result and an index ‘i’ initialized to 0.
Then we want to return the result of the ternary expressios. As we studied, recursive function need an exit statment, we will start from this one:

return i>=this.length
? newArr

If ‘i’ (that start at 0) is great or equal to the array length that call the method return the newArr (as would mean that we already processed all the array values).
If this is not the case then

: callback(this[i])
? this.myFilter(callback,newArr.concat(this[i]),++i)

Lets check if the callback function applied on the array value return true or false, (remember that you dont have to check with “===” or “==” true as any expression that evaluate to truthy value is true!)
In our case the callback function will check if the array value divided by 2 give 1 as reminder.
So if it does we are going to call the same myFilter function, but this time with some differences:

  1. We are going to pass our newArr array concatenating it with the actual value of the array so that is now populated with the first value that we know pass the callback function.

  2. We are going to add 1 to i but watch out

The first time I wrote the function, I did write i++ and the test went on maximum stack call (too much recursive iteration) and i couldn’t get where my logic was wrong.
Then I added the console.log(i) between the execution and saw that the variable ‘i’ was always 0 !.
That is because I did something that beginner may not know.
The following expressions are not the same :

a=i++ // assign to variable “a” value of i THEN increment it
a=i+1 // assign to variable “a” value of i+1
a=++i // INCREMENT i THEN assign the value of i to variable “a”

This mean I was always passing to myFilter the ‘i’ variable with value 0 !
So now that we know how to pass correctly the incremented value to our recursive function lets finish the explanation:

: this.myFilter(callback,newArr,++i)

So we just saw what happend if call back return a truthy value, but what if it return a falsy value ? We just call the recursive function again, this time not concateneting our newArr array with any value as it doesn’t satisfy the callback function.
In the end we just print the value after defining the callback function

var new_s = s.myFilter(function(item){
return item % 2 === 1;
});
console.log(new_s); //print [23,65,5]

Hope it will be usefull for somebody.

3 Likes

Always reading more experienced javascript coder’s work. Not new to coding, but new to javascript. Appreciate your thought out and explained code.

Thank you , it helps to see what others do, then, …I can find my way to making my “own”.

Array.prototype.myFilter = function(callback){
  // Only change code below this line
  var newArray = [];
  this.forEach(elm => callback(elm)?newArray.push(elm):null);
  // Only change code above this line
  return newArray;
};

It is great that you solved the challenge, but instead of posting your full working solution, it is best to stay focused on answering the original poster’s question(s) and help guide them with hints and suggestions to solve their own issues with the challenge.

We are trying to cut back on the number of spoiler solutions found on the forum and instead focus on helping other campers with their questions and definitely not posting full working solutions.

Thank you for understanding.

brother both are working correctly.

@francis.nguyen

You can post solutions that invite discussion (like asking how the solution works, or asking about certain parts of the solution). But please don’t just post your solution for the sake of sharing it.

We have set your post to unlisted. Thanks for your understanding.

1 Like

Good day!
Thanks for the feedback! It’s my first post and was not aware of the guideline. Just thought that my solution is probably more elegant than the solutions provided so i think it’s a good idea to contribute… is there a way? Cheers,
Francis

It has been decided to add only solutions that have a different logic flow, instead of adding alternative syntax for the same thing

How dose this code work and what line would be preferred over the other?

this.forEach((f) => (callback(f) ? false : true) || newArray.push(f));

this.forEach((f) => (callback(f) == false) || newArray.push(f));

personally I would use none of them as it makes things difficult to read, I would just if (!callback(f)) {...}

what do you not understand of those line of code? there are a ternary operator, and the other thing you would need to research is short-circuit evaluation

I see, I was thinking less code the better; but not if you can’t read it. Thanks for the article (short-circuit evaluation), it had the answer I was looking for.

Code golf (the fewer characters the better) is a very bad habit to develop. People on the internet will tell you its cool, but for professional development readability, maintainability, and efficiency/performance are far, far more important.

3 Likes

Yup, as @JeremyLT said…
Performance > Short Code. It’s just how you’re supposed to code.

That and I have to keep reminding myself that ‘debugging Jeremy’ is stupider than ‘development Jeremy’ and I need to write my code clear and simple enough that ‘debugging Jeremy’ will understand my code in the future. I leave future me comments to help future me understand what the hell I did if I get clever for performance reasons.

3 Likes

Here’s one of the easiest solutions, it might be right or wrong but it checks the list.

var newArray = [23, 65, 5];

It works.

Hi @oungthihamaung !

Welcome to the forum!

Thank you for your response.
This thread has not been active for over 8 months so I am going to close it.

Thanks!

2 Likes