1

destroyer([1, 2, 3, 1, 2, 3], 2, 3) should return [1, 1], but it returns [1, 2, 3, 1, 2, 3]. What is wrong with this code?

function destroyer(arr) {
  // Remove all the values
  var arg_num = arguments.length;

  var new_arr = arguments[0].filter(function(a){
    for (var i = 1; i < arg_num; i++){
      if (a === arguments[i]) a = false; 
    }
    return a;
  });

  return new_arr;
}

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

3 Answers 3

2

argument is used to get the list of arguments of current function. While performing filter you used argument, it gives argument of filter method. it differ from the destroyer method argument.

So store the destroyer method argument in one variable. Try this code.

function destroyer(arr) {
// Remove all the values
var args = arguments;
var arg_num = args.length;
var flag;
var new_arr = arguments[0].filter(function (a) {
  flag = false;
  for (var i = 1; i < arg_num; i++) {
    if (a === args[i]) {
      flag = true;
      break;
    };
  }
  if (flag)
    return false;
  else
    return true;
});
return new_arr;
}
console.log(destroyer([0, 2, 3, 0, 2, 3], 0, 3));

Hope this will help you.

Sign up to request clarification or add additional context in comments.

3 Comments

Your function will not work when the value in array is 0. You need to return true of false not the element.
Try this jsfiddle.net/exj1zux7/2 if the value is 0 and it's not the list to remove it will return that element from filter wich is falsy and it will not be on the list.
@jcubic Yeah you correct, now I updated my code. Thanks for your information.
1

You can instead use difference function from lodash library. It's a well tested and widely used utility library.

var _ = require('lodash');

var result = _.difference([1, 2, 3, 1, 2, 3], [2, 3])); // returns [1, 1]

2 Comments

"Should" is a strong word, given OP isn't using lodash.
@Oriol replaced should with can :)
1

The problem is that the arguments keyword is usually bound to the current function, which in this case is the anonymous function used in filter.

ES6 allows to fix this easily by introducing arrow functions, which don't bind arguments.

(function destroyer(arr) {
  var arg_num = arguments.length;
  return arguments[0].filter(a => {
    for (var i = 1; i < arg_num; i++){
      if (a === arguments[i]) return false;
    }
    return true;
  });
})([1, 2, 3, 1, 2, 3], 2, 3); // [1, 1]

However, note this function has cost n m where n is the number of elements in the array and m is the number of additional arguments. But could be better.

For example, if the additional arguments will always be numbers, you can sort them, and then use dichotomic searches. This will cost n lg(m).

Another approach would be using a hash table. It will still cost n m on the worst case, but only n on average.

If you don't want to implement that manually, you can use a ES6 set. Its specific cost will be implementation dependent, but is required to be sublinear on average.

(function destroyer(arr, ...args) {
  var s = new Set(args);
  return arr.filter(a => !s.has(a));
})([1, 2, 3, 1, 2, 3], 2, 3); // [1, 1]

1 Comment

Note that ES6 sets compare using the SameValueZero equality algorithm instead of the Strict Equality Comparison used by ===. They behave differently for NaN.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.