I need help understanding this "Seek and Destroy" Algorithm Solution [Solved]

So I’ve been chewing through this algorithm problem for a while, and @faustodc had a working solution similar to what I was trying for, I don’t understand his solution’s syntax. (I would PM him, but his last activity was back in October. :frowning: )

The comments are my own, to try and mentally break the code into chunks.
tl;dr, question is in bold at middle of page :slight_smile:

function destroyer(arr) {
var targets = Array.prototype.slice.call(arguments, 1);

//targets is the result of converting the "array-like" 
//arguments obj into a true array, starting from index 1 (excluding "arr"), 
//and goes until the end of the arguments object length.

So far, so good! :slight_smile: Here is where things break down for me:

Issue, I don’t understand how val is given a value in the filter callback function.

Making an educated guess at what this code does:

  1. loop through the length of targets (array of all additional arguments after the first "arr"ay)

  2. if a character in “val” exists in targets,* return true //*Edited, had this backwards.

  3. finish looping, returning true on each “true” hit of .indexOf

  4. End loop, return false. (Why… I’m not sure)

    return arr.filter(function(val){
    for(var i = 0; i < targets.length; i++){
    if(targets.indexOf(val) < 0 return true;
    }
    return false;
    });
    }

    //We return (end) the function with the result of the expression,
    //“arr.filter()” – filter takes a function as a “pass/fail” argument, runs
    //each entry in an array through that function, if the entry passes (“true”)
    //it is then put into a new array named whatever .filter was called on.

    //If it doesn’t (“false”) then it is left alone. Original array is not mutated.

    //(Although technically since arr is the only thing we’re working with,
    //it’s essentially overwriting the old “arr” with a new, identically named “arr”

Most of the previous algorithm problems I’ve either worked through on my own, or had to really break down the solutions to understand how the pieces work together, but with this one I’m just stumped. :confused:

I’ve dug through the MDN entr on the .filter method, and I can’t find anything about a parameter for the callback function, only references to .this (which isn’t being used in the solution)

I actually wasn’t able to get this solution to work. I think that there may be something missing from it and the if statement is malformed.

However, it looks like you have the basic understanding of it. The reason that you might return false after the loop is because if there are no matching values then you have to have to let the filter method know that there is nothing to add to the array.

@sceadgugenga – I just figured out why it probably didn’t work, a " < 0 " in the condition of the if statement didn’t make it over when I copy pasted. Oops. Fixed Now.

@sceadgugenga – That’s interesting! I copy/pasted the solution into the challenge prompt just to see what it would do, and it passed all of the prerequisites and the challenge was completed.

Here’s the full code, in case anyone wants to try it:
https://www.freecodecamp.com/challenges/seek-and-destroy ----

function destroyer(arr) {
var targets = Array.prototype.slice.call(arguments, 1);

return arr.filter(function(val){
for(var i = 0; i < targets.length; i++){
	if(targets.indexOf(val) < 0)
		return true;
        }
    return false;
    });
}

Returning false makes sense, have to give it a default response.

@PinkPanther901 - Hey there, nice to hear you’ve arrived at a similar conclusion to me!
Answering your question, when you use the callback function of .filter() any value that passes the test in it will get added to an array, which is the one that gets returned.
More information here:

The rest you seem to have it right, about your last paragraph, the parameter for the callback function is whatever value of arr that is being tested at that moment.
Please tell me if you got any other question

@sceadgugenga - It works: https://repl.it/FGGk/0

The updated version indeed seems to work. The original post had if(targets.indexOf(val) <return true which of course threw errors

@faustodc Hey! Thanks for taking the time to walk me through your solution. The filter callback function inheriting the value of the current index in the array as the value for the parameter makes perfect sense!

I was originally trying to use the for loop to check each [i]ndex of the main arg as the parameter for .indexOf, but that didn’t work.

Here is what my code ended up looking like! :smiley:

  var adlArgs = Array.from(arguments);
  adlArgs.shift();
  //So right now, this reads: adlArgs [index0 = 2, index1 = 3]
  console.log("New args is",adlArgs);


  //Now we go in and say, "Hey you first array! FILTER YO' SELF"
  //Filter based on the result of the function that checks:

return arr.filter(function(val){

for (var i = 0; i < arr.length; i++){
  if(adlArgs.indexOf(val) > -1){
  
  console.log("That number exists in both places, returning false.");
  return false; 
  }else{
    return true; 
  }
}//for loop

return false; //end of for loop, we are done.
  }); //filter function scope

} 

Your code is more concise than mine, but they’re similar. :slight_smile:

@sceadgugenga – Correct! I noticed the mistake and went back to fix it in my original post, also noting the error in my first reply. Sorry about that!