0

I am working on an assignment in which I am provided an array and a varying number of arguments. I have to remove all values from the initial array that are of the same value of these arguments. Here is my code:

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);
          }
      }
  }
  return arr;
}

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

I am getting correct output for some patterns of arrays and arguments but for the example above, it should only output [1] but my code is outputting [1, 2]. Any help would be appreciated. Thanks.

1
  • 1
    Might you be able to provide the prompt for this particular assignment? I'm having trouble understanding what you're going for. Commented Jan 5, 2016 at 5:42

3 Answers 3

1

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));

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

2 Comments

I was curious about the Set solution and holy cow, it's dozens of times faster on big arrays and even with very few elements (less than 10 or 5), it's almost always faster. Even funnier: IE11's Set implementation is twice faster than V8's... The jsperf
@masonc15 - Did this answer your question?
0

make it (using indexOf and while loop)

function destroyer(arr) {
  for(var i = 1; i < arguments.length; i++)
  {
          var index = arr.indexOf( arguments[i] );
          while( index != -1 )
          {
              arr.splice(index, 1);
              console.log(arr);
              index = arr.indexOf( arguments[i] );
          }
  }
  return arr;
}

you need to check it again and again rather than checking it only once unless index is -1

Comments

0

With the same exercise, even though the instruction stated to use the Arguments object, this solution works:

function destroyer(arr, ...valsToRemove) {
return arr.filter(elem => !valsToRemove.includes(elem));
}

Comments

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.