I have this code which is supposed to iterate over each item in an array, removing items based on some condition:
//iterate over all items in an array
//if the item is "b", remove it.
var array = ["a", "b", "c"];
array.forEach(function(item) {
if(item === "b") {
array.splice(array.indexOf(item), 1);
}
console.log(item);
});
Desired output:
a
b
c
Actual output:
a
b
Obviously the native forEach method doesn't check after each iteration whether the item has been deleted, so if it is then the next item is skipped. Is there a better way of doing this, aside from overriding the forEach method or implementing my own class to use instead of an array?
Edit - further to my comment, I suppose the solution is to just use a standard for loop. Feel free to answer if you have a better way.
One possibility would be to use the
array.slice(0)
function, which creates a copy (clone) of the array and thus the iteration is separated from the deletion.Then the only change to the original approach using
array.forEach
would be to change it toarray.slice(0).forEach
and it will work:After the forEach, the array will contain only
a
andb
.A jsFiddle demo can be found here.
Lets see why JavaScript behaves like this. According to the ECMAScript standard specification for
Array.prototype.forEach
,when you delete an element at index 1, the element at index 2 becomes the element at index 1 and index 2 doesn't exist for that object.
Now, JavaScript looks for element 2 in the object, which is not found, so it skips the function call.
That is why you see only
a
andb
.The actual way to do this, is to use
Array.prototype.filter
Another possibility would be to use the
array.reduceRight
function to avoid the skip:After the
reduceRight
, the array will contain onlya
andc
.All the above mentioned answers just fail or not retain the original array to be passed elsewhere, if we were to remove two elements at a specific index and continue iterating from the immediate element. for suppose, I have an array
I want to splice away two elements if there is successive combination of ford and chevy.
So this way I am replacing the couple spliced elements with a null so that I could adapt to non updating iteration index of forEach(). Then I can clean the array of any inserted nulls once the iteration is complete, and array is ready to be handed off.
This can be a better way of not hampering anything and absoloutely solving this spooky behavior of javascript.