This algorithm is actually called Seek and Destroy
.
1 |
You will be provided with an initial array (the first argument in the destroyer function), followed by one or more <a class="zem_slink" title="Argument" href="http://en.wikipedia.org/wiki/Argument" target="_blank" rel="wikipedia" data-mce-href="http://en.wikipedia.org/wiki/Argument">arguments</a>. Remove all elements from the initial array that are of the same value as these arguments. |
You know your code has passed when:
1 2 3 4 5 |
destroyer([1, 2, 3, 1, 2, 3], 2, 3) should return [1, 1] destroyer([1, 2, 3, 5, 1, 2, 3], 2, 3) should return [1, 5, 1]; destroyer([3, 5, 1, 2, 2], 2, 3, 5) should return [1] destroyer([2, 3, 2, 3], 2, 3) should return[] destroyer(["tree", "hamburger", 53], "tree", 53) should return ["hamburger"] |
When initially unsure, I always visit the helpful links I am provided to help me reach a solution. I knew that filtering an array was part of the solution, so I checked out the Array.filter() link first.
According to MDN‘s article, the .filter() method creates a new array with all the elements that pass the test implemented by the provided function:
1 |
arr.filter(callback, [, thisArg]); |
Let’s break this method down a bit. First to discuss is the meaning of “callback” and its role in arr.filter():
The callback: is a function to test each element of an array. It is invoked with arguments (element, index, array). It is returned true to keep the element, and returned false to discard it.
thisArg: Optional. Value to use as “this” when executing the callback. To learn more about “this”, please visit:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
On the first go around, arr.filter() just didn’t seem to provide me with obvious answers on its own. I also wasn’t quite sure how I was going to deal with an array and one or more arguments at the same time, so I checked out the second “helpful link”, Arguments object:
The Arguments object: is an array-like object corresponding to the arguments passed to a function.
arguments object: is a (built-in) local variable available within all functions. You can refer to a function’s arguments within the function by using the arguments object. This object contains an entry for each argument passed to the function. This object contains an entry for each argument passed to the function, the first entry’s index starting at 0. For example, if a function is passed three arguments, you can refer to them as follows:
1 2 3 4 5 |
arguments[0]; arguments[1]; arguments[2]; |
The arguments can also be set:
1 |
arguments[1] = 'new value'; |
Contrary to appearances, the arguments object is NOT an Array. It is similar to an array, but it doesn’t have any Array properties except .length. For example, it doesn’t have the pop() method. It also doesn’t have the .shift() method, etc. However, it can be converted to a real Array:
1 |
var args = Array.prototype.slice.call(arguments); |
You can also use the Array.from() method to convert arguments to a real Array:
1 |
var args = Array.from(arguments); |
So now it’s time to apply what we have gone over so far with how it applies to my solution to the challenge:
First of all, we were initially provided with the following:
1 2 3 |
function destroyer(arr) { return arr; } |
1 |
var args = Array.prototype.slice.call(arguments); |
1 |
return args.indexOf(element) <a class="zem_slink" title="Relational operator" href="http://en.wikipedia.org/wiki/Relational_operator" target="_blank" rel="wikipedia" data-mce-href="http://en.wikipedia.org/wiki/Relational_operator">===</a> -1; |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function destroyer(arr) { var args = Array.prototype.slice.call(arguments); return arr.indexOf(arguments) === -1; }; destroyer([ 1, 2, 3, 1, 2, 3 ], 2, 3); |
1 |
<var>arr</var>.filter(<var>callback</var>[, <var>thisArg</var>]) // thisArg is optional and is briefly explained at the beginning of the post |
filter(): calls a provided callback function once for each element in an array, and constructs a new array of all the values for which callback returns a true value or a value that coerces to true. callback is invoked only for indexes of the array which have assigned values. It is not invoked for indexes which have been deleted or never been assigned values. Array elements which do not pass the callback test are skipped, and are not included in the new array.
There is one last piece of the puzzle that needs explaining: the .indexOf() method:
.indexOf(): returns the first index at which a given element can be found in an array, else -1 if it is not present.
So function destroyer(arr) {} has
- one parameter called arr, and the arguments passed to function destroyer()within the [], make up the elements of arr.
-
The two numbers which follow the array are the argument objects.
-
args is a variable which I created to store the values of the arguments object. At the same time, I am converting the arguments into a real array with Array.prototype.slice.call(arguments). Now there are two array arguments present instead of one.
-
args.splice(0,1); splices the first (original) array (arr) away from the new arguments array stored in the args variable and returns it in the form of arr.filter();
-
The (original) array (arr), which is the first argument passed to the destroyer() function, is returned in the form of return arr.filter(), and its elements are filtered against the elements in the new args array.
-
The two steps described in #5 are represented by return arr.filter(function(element) { return args.indexOf(element) === -1; }); } What this means is that whichever elements are present in the first argument (the original array arr) but are not present in the arguments array are the only elements returned. In the case below, it is [1,1]. That is all that is left of the original array, and all that was unique to the array (arr).
Solution in ES5:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
function destroyer(arr) { var args = Array.prototype.slice.call(arguments); args.splice(0, 1); return arr.filter(function(element) { return args.indexOf(element) === -1; }); } destroyer([ 1, 2, 3, 1, 2, 3 ], 2, 3); |
Solution in ES6:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
function destroyer(arr) { const args = Array.prototype.slice.call(arguments); args.splice(0, 1); return arr.filter(element => args.indexOf(element) === -1); } destroyer([ 1, 2, 3, 1, 2, 3 ], 2, 3); |
This was first published here on May 4, 2016 @ 14:49. It was part of freecodecamp.org’s Basic JavaScript Algorithm Scripting for the Front End Development certification.
Related articles
Comment Policy: Your words are your own, so be nice and helpful if you can. Please, only use your real name and limit the amount of links submitted in your comment. We accept clean XHTML in comments, but don't overdo it please. Comments are moderated, so spammy or malicious links will be removed.