FCC Bonfire Series 117: Seek and Destroy

Seek and Destroy is a nice way to get into the arguments object, which I’ll explain shortly. This exercise will have us write a function that takes an array as the first argument, and any amount of additional arguments -numbers-. The function will remove every number passed as argument that has matches inside the first arguments array.

First, let me briefly explain what the arguments object is. The arguments object is an Array-like object that can be accessed as a local variable inside any function. This object contains every argument passed to the function, starting at index 0. This is the point where many assume that the arguments object is actually an Array. Well, it isn’t, the only Array method present in the arguments object is length. It also has a few other properties, such as arguments.callee (currently executing function) and arguments.caller (reference to the function that called the current function).

Since our problem function should accept an arbitrary number of arguments, we should -and must- make use of the arguments object. But, since we cannot simply transverse the arguments object as if it were an array, let’s first turn it into an actual array. There is a few ways to tackle this issue, first, we have Array.prototype.slice.call(arguments), which looks confusing -we haven’t touched on call yet- and actually prevents some optimizations in JavaScript engines. Then, we may also just loop over the properties in the arguments object and push them into a new array; and that’s exactly what we are going to be doing:

function destroyer(arr) {
  var mustRemove = [];
  for (var i = 1; i < arguments.length; i++) {
    mustRemove.push(arguments[i]);
  }
  // Do some magic.
}

You may notice that we are looping through the arguments object starting at index 1. We know that the first argument -index 0- is the array that we need to work on, so numbers to be removed will range from index 0 up to the end of the arguments object.

At this point you may be wondering why we are actually turning the arguments object into an array, well, we need to use a few Array methods that the arguments object does not have, so bear with me until we get there.

We now have two (2) arrays, one of them is the original array, from which we need to remove every item present in the second array. Let’s use filter and indexOf, and give it a shot:

function destroyer(arr) {
  var mustRemove = [];
  for (var i = 1; i < arguments.length; i++) {
    mustRemove.push(arguments[i]);
  }
  return arr.filter(function(item) {
    if (mustRemove.indexOf(item) >= 0) {
      return false;
    } else {
      return true;
    }
  });
}

Looking good! That should work, we are merely filtering the array and checking whether the current array item exists within the mustRemove array, by using indexOf, as we have done in the past. Let’s try to make it a little more ‘compact’, and practice some ternary goodness:

function destroyer(arr) {
  var mustRemove = [];
  for (var i = 1; i < arguments.length; i++) {
    mustRemove.push(arguments[i]);
  }
  return arr.filter(function(item) {
    return mustRemove.indexOf(item) >= 0 ? false : true;
  });
}

Great! We’ve used a combination of filter, indexOf and the ternary operator for great success! Get coding and try to come up with your own function!