0

I can't get my head around this, i'm using filter to loop through an array and filter out all the integers passed as arguments ,i'm not limited in the number of arguments.

But i'm stuck here when it's about to get back to the function the value of the arguments object, at least more that once.

In my code below, obviously it's not fully working because i'm doing a return within the for…in loop, this is where i don't get how I can get the this second loop without having i re-initialised to 0

function destroyer(arr) {
  var args = arguments.length;
  var arg0 = arguments[0];
  var Nargs = Array.prototype.slice.call(arguments, 1);
  var newArr = [];
  
  
    newArr = arg0.filter(filtre);
    
    /*Only the first argument is 
    filtered out,here it's the value "2",
    but should filter out [2,3].
    The expected result is [1,1]*/
    console.log(newArr);
    return newArr;    
  
     function filtre(e){
 
         for (var i in Nargs){

           return e !== Nargs[i];
         } 
     }
}


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

Hope this is clear enough,

Thanks for any input !

Matth.

Matthieu Ducorps
  • 170
  • 1
  • 1
  • 16
  • filter must return a Boolean indicating weather the value needs to be filtered or not – Basilin Joe Mar 29 '17 at 03:53
  • 1
    So `destroyer([1, 2, 3, 1, 2, 3], 2,3);` should return `[1, 1]`? – Gerrit0 Mar 29 '17 at 03:57
  • @Gerrit0 yes exactly! Adding this to the question for better clarity. – Matthieu Ducorps Mar 29 '17 at 03:58
  • @CodeBean, ok, but how do you check each arguments separately for the same table ? – Matthieu Ducorps Mar 29 '17 at 03:59
  • [Don't use `for…in` enumerations on arrays!](https://stackoverflow.com/q/500504/1048572) – Bergi Mar 29 '17 at 04:10
  • @Bergi, from what JS is telling me here `Nargs` is an object not an array. `console.log(typeof Nargs); ` as well as the [mdn doc](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments) – Matthieu Ducorps Mar 29 '17 at 04:13
  • 1
    @MatthieuDucorps `Nargs` is an `Array` as it was created by `slice`, but even `arguments` is an arrary-like object that should be iterated not enumerated. And yes, they're all objects, so `typeof` won't help you distinguishing them. – Bergi Mar 29 '17 at 04:17
  • 1
    `console.log(typeof [])` also logs object. Nargs is an array since you used `Array.prototype.slice.call` on it. – Gerrit0 Mar 29 '17 at 04:17
  • ok, now i'm confused, it 's reported as an object, but has to be treated as an array :D. I found Javascript a bit dirty sometimes :( – Matthieu Ducorps Mar 29 '17 at 04:22
  • 1
    Javascript can be confusing, in this case you might find [Array.isArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray) to be helpful. – Gerrit0 Mar 29 '17 at 04:26

2 Answers2

1

While rgthree provided a solution very similar to what you already had, I wanted to provide a solution that takes advantage of newer ES6 features for modern browsers. If you run this through Babel, it will result in essentially the same code as in that solution, though it will still require a shim for the includes call.

function destroyer(source, ...args) {
    return source.filter(el => !args.includes(el));
}

Explanation:

...args uses the spread operator to get all but the first argument into an array named args.

We can directly return the filtered array, assuming you don't need to log it and that was just for debugging.

el => !args.includes(el) is an anonymous arrow function. Since no braces are used, it will automatically return the result of the expression.

Since args is an array, we can directly use Array.prototype.includes to check if the current element is in the arguments to be removed. If it exists, we want to remove it and thus invert the return with !. An alternative could be the following: el => args.includes(el) == false.

Gerrit0
  • 7,955
  • 3
  • 25
  • 32
0

Since your return statement in your filtre function is always executed on the first run, it's only returning the whether the first number in Nargs is equal to the current item. Instead, you can use indexOf for full browser support (which returns the index of the item in an array, or "-1" if it's not in an array) instead of a loop (or includes, or a loop, etc. as shown further below):

function destroyer(arr) {
  var args = arguments.length;
  var arg0 = arguments[0];
  var Nargs = Array.prototype.slice.call(arguments, 1);
  var newArr = [];
  
  function filtre(e){
    return Nargs.indexOf(e) === -1;
  }
  
  newArr = arg0.filter(filtre);
  console.log(newArr);
  return newArr;
}
destroyer([1, 2, 3, 1, 2, 3], 2,3);

If you don't need Internet Explorer support, you could use Array.includes:

  function filtre(e){
    return !Nargs.includes(e);
  }

And finally, if you really wanted to use a loop, you would only want to filter an item (return false) once it's found otherwise allow it (return true):

 function filtre(e){
   for (var i = 0, l = Nargs.length; i < l; i++) {
     if (e === Nargs[i])
       return false;
   } 
   return true;
 }
rgthree
  • 7,217
  • 17
  • 21
  • 1
    Or even better: `Nargs.includes(e)`. – Gerrit0 Mar 29 '17 at 04:03
  • @Gerrit0 I don't like suggesting methods that won't work in all widely used browsers but, yes, if OP didn't care about it working in IE then he/she could use `Array.include` – rgthree Mar 29 '17 at 04:05
  • ok now i have to read again the doc of indexOf cause I don't get it :D – Matthieu Ducorps Mar 29 '17 at 04:07
  • 1
    @MatthieuDucorps I added some more to the answer. `indexOf`returns the index of the item in the array, or `-1` if it's not in the array at all. So, if `Nargs.indexOf(e)` is equal to -1, then it's not in the array and the filtre function returns true to keep it. I've also included more code showing `Array.include` that Gerrit0 suggests and if you *really* wanted to do it in a loop. – rgthree Mar 29 '17 at 04:14
  • Thanks a lot ! @rgthree will go through all those solutions to get it properly. – Matthieu Ducorps Mar 29 '17 at 04:24