freeCodeCamp Challenge Guide: Seek and Destroy

Basic, but long code.

function destroyer(arr)
{
  // Remove all the values
  
  //Turn to a real array
  var args = [];
  args = Array.from(arguments);
  
  var filtered = [];
  var val;
  
  //Filter 'argument[0]'(args[0])
  for (i = 0; i < args[0].length; i++) //args[0]
    {
      for(j = 1; j < arguments.length; j++) //args[1] =<
        {
          if(args[0][i] == args[j])//Check whether args[0] elements equal to others
            {
              break; // Stops if equal, lead to check next args[0] element
            }
          else
            {
              val = args[0][i]; 
              
              //Push only after checked by all following args
              if (j == arguments.length - 1) 
                {
                  filtered.push(val);
                }
              continue;
            }
        }
    }
  return filtered;
}

destroyer(["tree", "hamburger", 53], "tree", 53);

The output is correct for all cases. But still, the code is not accepted. Whereā€™s the problem?

function rem(value) {
  return value !== this; 
}

function destroyer(arr) {
  var args = Array.from(arguments);
  for (var i=1; i<args.length; i++) {
    arr=arr.filter(rem, args[i]); 
  }
return arr;
}

Here is mine using .include()

function destroyer(arr) {
  var args = Array.from(arguments);
  var firstArg = args.shift();
    
  var returnedArg =[];
  
  for (i=0; i<firstArg.length; i++) {      
    if (args.includes(firstArg[i])===false){
    returnedArg.push(firstArg[i]);
  }}
  
  return returnedArg;

  
}

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

Logic: If something in the array is not in the arguments, then put that number from array to a new array.

My ES6 ā€œone-linerā€:

function destroyer(arr) {
  return arr.filter(x=>![...arguments].slice(1,arguments.length).includes(x));
}
15 Likes

Hereā€™s my solution. Using .filter and .indexOf:

function destroyer(arr) {

  var args = Array.from(arguments);
  
  var result = args.shift().filter(function (value) {
    if (args.indexOf(value) < 0) {
      return true;
    }
  });
  
  return result;
}
1 Like

Hi, I was doing fine on all of the other exercises until this one. Can someone explain why filter(Boolean) only returns true values? I thought that Boolean evaluated to true OR false?

2 Likes

HereĀ“s my version using the same tricks. This was a tough one for me but I am glad I took the time and effort and now I actually understand the idea of the callback function.

function destroyer(arr) {

var myArr = [].slice.call(arguments, 1);

var finalArr = arr.filter(function(x) {

return myArr.indexOf(x) === -1;

});

return finalArr;
}

1 Like

I kept using arguments inside the callback function of filter, and was wondering for the longest time why it wasnā€™t working.

1 Like

Managed to simplify it down to this after lots of playing around.

function destroyer(arr) {
  var args = Array.prototype.slice.call(arguments);
  return args.shift().filter(function(initial){return this.indexOf(initial)<0;},args);
}
destroyer([1, 2, 3, 1, 2, 3], 3, 2);
2 Likes

// without filter
function destroyer(arr) {
var l=arr.length*arguments.length;
var i=0,j=0,k=1;
while(i<l)
{
if(arr[j]===arguments[k])
{
arr.splice(j,1);
k=1;
}
else{
k++;
}
if(k==arguments.length)
{
j++;
k=1;
}
i++;

}

return arr;
}

I donā€™t understand why my code wont pass. Can someone please enlighten me?

function destroyer(arr) {
var newArr = [];
for (var i = 0; i < arguments[0].length; ++i){
for(var j = 1; j < arguments.length; ++j){
if (arguments[0][i] === arguments[j]){
newArr.push(arguments[i]);
}
else {
return;
}
}
}
return newArr;
}

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

Hey TeeJay,

The increment operator (++) is supposed to go after the integer variable, so it should be i++ and j++ in your for loops.

The condition for your if statement dictates that if a value in arguments[0][i] is equal to the arguments we are trying to exclude from the array (i.e. arguments[j]), it should be pushed to newArr. What this means is that youā€™re actually pushing the values you donā€™t want to the new array. Instead of pushing those values to newArr, you could simply delete them from arr. This also means you no longer need use a new array.

The else statement you implemented also meant that whenever your if condition was false, the for loops would be broken out of (which isnā€™t what you want as you want the for loop to iterate over all the values in arr), and nothing would be returned as you didnā€™t place anything after the return keyword. The else statement is actually unnecessary, as shown in my reworking of your code below.

Using the delete keyword to remove the unwanted values from arr leaves null values in their place and youā€™ll end up with:
[1, null, null, 1, null, null]

So, when returning arr, filter out the null values using arr.filter(Boolean);.

I reworked your code as follows and it now passes:

function destroyer(arr) {
  for (var i = 0; i < arguments[0].length; i++){
    for(var j = 1; j < arguments.length; j++){
      if (arguments[0][i] === arguments[j]){
        delete arguments[0][i];
      } 
    }
  }
  return arr.filter(Boolean);
}

This solution above is quite similar to the Basic Code Solution, minus the use of Array.prototype.slice.call() to create an array of arguments.

I hope Iā€™ve helped.

7 Likes

Thank you @MarioAleixo! I had been scratching my head on this one for a while. Great explanation and you also helped me understand why we need to filter the Boolean values.

1 Like

I really appreciate all the help I get in these guides, but I just wanted to say that the second hint threw me a bit of the scent on this challenge and that the ultimate solution was pretty much what I was thinking it was going to be before I read the hints. I know I should have tried to write the code as I saw it in my head before looking for hints, but just throwing it out there that maybe Hint 2 could be removed or changed because I donā€™t think there are many solutions that actually use those methods.
Again, thanks for all the help.

3 Likes

This is my solution here. Tried to make it simpler.

function destroyer(arr) {
  // Remove all the values
  var targets = Array.prototype.slice.call(arguments, 1);
  
  var results = arr.filter(function(e) {
return this.indexOf(e) < 0;
  }, targets);  
  
  return results;
}

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

How does val get initiated of defined in the intermediate explanation?
Iā€™m not understanding that particular part.

Thank you

This is because he used the filter() method on the array arr. With this method it passes each and every element in the array arr to the variable val one at a time.

This is the Syntax of filter method

array.filter(function(currentValue, index, arr), thisValue)

where currentValue :- is the current element of the array that is given to the function. I.e in our case the variable val,

index, arr and thisValue are optional and arenā€™t used in the example.

More Useful links below:-
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

1 Like

This is my solution. I decided to use some ES6 because I got a little bitter looking at all the extra code.

var args = Array.prototype.slice.call(arguments, 1);
  
return arr.filter(function(val){ return args.every(x => x !== val); });

I tried to use for loops as little as possible.

EDIT: Decided to change the empty arg array and for loop in favor of Array.prototype.slice.call(arguments, 1); that everybody has used. Never thought about it and did some research on it on the MDN.

1 Like

  • i get the destroyers with spread operator minus the first argument
  • then filter the first argument aka the array
  • num is each item in the array
  • only nums that arenā€™t in the destroyers array get returned
5 Likes

my solution

  1. create a fiterList to store extra arguments that after arr (more about arguments object)
  2. create a filter function for arr by indexOf
function destroyer(arr) {
    var filterList = [];
    
    for (var i = 1; i < arguments.length; i++) {
        filterList.push(arguments[i]);
    }

    return arr.filter(function(val) {
        return filterList.indexOf(val) < 0;
    });
}

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