0

I was attempting to use .forEach to remove the contents of one array(ignore) from another array(input).

As an example in the below I would expect the input array to contain "b" and "h" however it contains "g" and "h" when I run this.

curious why I am not getting my expected results and if this is a good method.

var input = ["a", "b", "g", "h"],                                               
    ignore = ["b", "h"];                                                        

var newInput = function(element, index, array){                                 
    if (input.indexOf(ignore[index]) > -1){                                     
       input.splice((ignore[index]), 1)                                        
    }                                                                           
}                                                                               

  ignore.forEach(newInput);
4
  • can you share what the output should be Commented Sep 15, 2015 at 4:46
  • With ignore set as ["b", "h"] I am expecting input to contain ["a", "g"] Commented Sep 15, 2015 at 4:49
  • @imnothardcore : did you dry run your code? I did and same you given code will give you the ["b", "h"] Commented Sep 15, 2015 at 4:58
  • 1
    ignore[index] is precisely equal to element, right? You can't pass the element to splice, you have to pass the position. Commented Sep 15, 2015 at 6:33

4 Answers 4

1

You should use Array.prototype.filter instead

var input = ['a', 'b', 'g', 'h']
var ignore = ['b', 'h']
var newInput = input.filter(function (el) {
  return ignore.indexOf(el) === -1
})

Note that input remains unchanged

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

Comments

1

Replace your conditionals with input.indexOf(element) > -1.

Since you are forEach-ing the ignore array, ignore[index] is the same as element.

And change splice to splice(input.indexOf(element), 1).

Array.splice() takes index as first arguments, and you are using the element instead.

Comments

1

Array#filter is probably the best approach, but if you want to remove the ignored elements in-place, as I infer from your use of splice, you can do:

function ignore_elements(input, ignore) {
  var i = 0;
  while (i < input.length)
    if (ignore.indexOf(input[i]) !== -1) input.splice(i, 1);
    else i++;
}

By looping over the elements in the input, instead of ignore, you can more easily eliminate all occurrences of the elements to be ignored, not just the first one.

2 Comments

I have seen some discussion of people suggesting a while and for loop over foreach and filter. what advantages does it offer? Also I like your idea of looping the input to get them all. Not needed in my application of this but probably better practice. Thanks
There's no hard and fast rule. However if you're filtering or mapping then filter and map are typically more succinct and readable.
1
var input = ["a", "b", "g", "h"],
    ignore = ["b", "h"];                        

var newInput = function(element, index, array){
    if (input.indexOf(ignore[index]) > -1) {
       input.splice(input.indexOf(ignore[index]), 1)
//                  ^^^^^^^^^^^^^  added this
    }
} 

ignore.forEach(newInput);

but that code could be cleaner, e.g. ignore[index] is element

var input = ["a", "b", "g", "h"],
    ignore = ["b", "h"];

var newInput = function(element) {
    var index = input.indexOf(element);
    if (index > -1){
       input.splice(index, 1)
    }
}

ignore.forEach(newInput);

If you really want to impress the girls

var input = ["a", "b", "g", "h"],
    ignore = ["b", "h"];

var newInput = function(element, index) {
    ~(index = input.indexOf(element)) && input.splice(index, 1);
}

ignore.forEach(newInput);

I'll let you figure out that one liner :p

mutliple deletions

var newInput = function(element) {
    var index;
    while (~(index = input.indexOf(element)))
        input.splice(index, 1);
}

ignore.forEach(newInput);

1 Comment

It's very confusing to provide the index parameter to the callback, when it is not needed and not used, and then redefine it to mean something entirely else. I supposed it's intended to avoid having to spend one line declaring a variable, but come on. Also, although the OP did not say so explicitly, it's reasonable to assume that he wants to remove all occurrences of an ignored element, not just the first one.

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.