Seek & Destroy - trouble understanding .filter()

function destroyer(arr) {

  var myArgs = [];

  for (i =1; i < arguments.length; i++) {
    myArgs.push(arguments[i]);
  }
  
 
  return arr.filter(function(val) {
    return myArgs.indexOf(val) === -1; 
    });  
  } 

destroyer([1, 2, 3, 1, 2, 3], 2, 3);

I passed the challenge with the above code. On some advice from the chat room I changed my original .filter enter which was hard coded:

return arr.filter(function(val) {
    return (val != myArgs[0] && val != myArgs[1] && val != myArgs[2]);

I know this is a bad coding practice, but it makes sense to me. The answer:

 return arr.filter(function(val) {
    return myArgs.indexOf(val) === -1; 
    });  

Is sadly making my head hurt in frustration! Could someone break down what is happening here so I can try to make sense of this? Thanks :slight_smile:

1 Like

If a value is not found in an array, calling .indexOf with that array will return -1. So arr.filter() will return an array of values that are not found in myArgs.

A synonym to
myArgs.indexOf(val) === -1
is
!myArgs.includes(val).

2 Likes

Ah perfect, this clears it up for me. Thank you :slight_smile:

Oh man! I can’t tell you how hard it was to fully understand how .filter() works. Even after reading through this thread I was still confused. So after much effort, time, research and experimentation I think I finally understand it. Out of empathy for others I am going to post my code here with detailed explanation of how it all works. For you experts out there, please correct me on anything points I may be wrong about. Just so you know I am aware that you can nest testFunction inside of the arr.filter() statement but its easier to understand with them separated like I have them. So here is without any comments:

.

function destroyer(arr)
{
var myArgs = [];
// This myArgs array variable will be used to hold the last two arrguments “tree” and 53 (arrgument[1], and arrgument[2]) which are being passed through the destroyer function. The for loop below pushes the last argument values into the myArgs array. By initializing i=1 instead of i=0 the for-loop skips the first argument[0] (argument[0] is the same thing as “arr”)
for (i =1; i < arguments.length; i++) {
myArgs.push(arguments[i]);
}
//console.log(myArgs);
//myArgs array now contains [“tree”, 53]

// tests if “tree” and 53 are in the arr array;
function testFunction(val) {
return myArgs.indexOf(val) === -1;
}
//.indexOf returns the index of the first occurrence of the specified value; or it returns -1 if the value was not found. So -1 === -1 would return true.

//The return statement below passes the array values [“tree”, “cheese”, 53, “hamburger”] found in “arr” array into the testFunction one at a time. During each cylce, the testFunction tests the individual arr element and returns a true or false value back to .filter. And finally .filter returns a filtered version of the arr array [“cheese”, “hamburger”] to the destroyer() function.

//So to explain it in more depth; if the testFunction returns a value of “true” to .filter it means it didn’t find that value in the myArgs array (for example myArgs.indexOf(“hamburger”) would return true), in which case .filter leaves that element in the arr array. However, myArgs.indexOf(“tree”) === -1; would retun “false” to .filter because it DID find “tree” in myArgs array. In which case, .filter will remove the “tree” element from the arr array.

return arr.filter(testFunction);
}

destroyer([“tree”, “cheese”, 53, “hamburger”], “tree”, 53); //returns [“cheese”, “hamburger”]

7 Likes

Filter was tricky for me at first too. MDN explanations are not always the clearest, but their description for .filter is good:

filter() calls a provided callback function once for each element in an array, and constructs a new array of all the values for which callback returns a value that coerces to true.

That’s the secret to understanding

return myArgs.indexOf(val) === -1;

That actually returns true or false when evaluated. True when the value is not found (when indexOf === -1) or false (when indexOf is anything else).

1 Like

awesome job explaining this, thank you!

This was a great explanation, thank you very much. .filter is the hardest thing for me to understand.

However I do have a question about “val”. How does testfunction know that “val” should be myArgs values? To me we never told the computer that.

That part I am not understanding.

1 Like

It is so simple, tough really hard to comprehend!

This helped me a lot! Thanks so much for the explanation!

Of course I am also a beginner …

Higher order functions are hard to understand. But I have to practice through the function
(I saw here somewhere …) I could understand the nature of it.

And I think that the key to higher order functions is reduce. If you can understand the function
map, filter. I’m sure you can understand includes, some, and so on.

And understand some of the higher order functions through external resources …

I did that too…:smiley: