When you do the .splice() to remove an item, it moves the elements after it down a spot in the array and that will cause your for loop to miss the next element if it happens to also be a match. You can fix that by decrementing your for loop index after removing an item or, (my favorite) you can just iterate the array from back to front and then the .splice() won't affect any future iterations.
Using your general code structure, here's the decrement solution:
function destroyer(arr) {
for(var i = 1; i < arguments.length; i++)
{
for(var j = 0; j < arr.length; j++)
{
if(arguments[i] == arr[j])
{
arr.splice(j, 1);
--j;
}
}
}
return arr;
}
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));
Using your general code structure, here's the reverse iteration solution:
function destroyer(arr) {
for(var i = 1; i < arguments.length; i++)
{
for(var j = arr.length - 1; j >= 0; j--)
{
if(arguments[i] == arr[j])
{
arr.splice(j, 1);
}
}
}
return arr;
}
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));
You can also use other array helper functions to leverage more of the native array functionality:
function destroyer(arr) {
var removes = Array.prototype.slice.call(arguments, 1);
return arr.filter(function(item) {
return removes.indexOf(item) === -1;
});
}
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));
Going with an ES6 Set for a little more potential efficiency:
function destroyer(arr) {
var removes = new Set(Array.prototype.slice.call(arguments, 1));
return arr.filter(function(item) {
return !removes.has(item);
});
}
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));
FYI, in the previous code example, I tried to do:
var removes = new Set(arguments);
as it seems cleaner and that works great in IE and Chrome, but a bug in Firefox keeps it from working there. The arguments in ES6 is supposed to be an iterable that you can pass to the Set constructor, but Firefox has not yet implemented that properly yet. There is an open Firefox bug on that topic that is being worked on. So, I backed this code example off to make a copy into a real array and pass the array to the constructor instead.
Another possibility is to use ES6 rest parameters:
function destroyer(arr, ...items) {
var removes = new Set(items);
return arr.filter(function(item) {
return !removes.has(item);
});
}
var result = destroyer([3, 5, 1, 2, 2], 2, 3, 5);
document.write(JSON.stringify(result));