I have the following context:
/
obj.forEach(function(user, index){
var userName = user.name;
console.log(index, userName);
if(index === 5 || index === 2){
obj.splice(index, 1);
}
});
I am using a forEach
loop and splice
to remove the item in position 5
and 2
on the obj
array. But for some reason its not working properly.
What am I doing wrong?
I have the following context:
https://jsfiddle/eqntaqbt/2/
obj.forEach(function(user, index){
var userName = user.name;
console.log(index, userName);
if(index === 5 || index === 2){
obj.splice(index, 1);
}
});
I am using a forEach
loop and splice
to remove the item in position 5
and 2
on the obj
array. But for some reason its not working properly.
What am I doing wrong?
Share Improve this question edited Apr 2, 2016 at 18:35 gespinha asked Apr 2, 2016 at 18:30 gespinhagespinha 8,50717 gold badges59 silver badges96 bronze badges 2- It is working properly.. Don't see the logged userName, check the array logged at the last in your filddle. – Rajaprabhu Aravindasamy Commented Apr 2, 2016 at 18:35
- Just updated the question – gespinha Commented Apr 2, 2016 at 18:38
3 Answers
Reset to default 7Your code is splicing while looping. Spliced elements are accessed even they are no more existing. That leads to undefined elements.
You may consider Array#filter
var obj = [{ "index": 0, "name": "Odonnell Noble", "gender": "male", "pany": "DIGIQUE", "eail": "[email protected]" }, { "index": 1, "name": "Marie Oneal", "gender": "female", "pany": "CANOPOLY", "email": "[email protected]" }, { "index": 2, "name": "Adrienne Marsh", "gender": "female", "pany": "XOGGLE", "email": "[email protected]" }, { "index": 3, "name": "Goff Mullins", "gender": "male", "pany": "ENDIPIN", "email": "[email protected]" }, { "index": 4, "name": "Lucile Finley", "gender": "female", "pany": "AQUASSEUR", "email": "[email protected]" }, { "index": 5, "name": "Pitts Mcpherson", "gender": "male", "pany": "QUARX", "email": "[email protected]" }];
obj = obj.filter(function (user, index) {
return (user.index !== 5 && user.index !== 2);
});
document.write('<pre>' + JSON.stringify(obj, 0, 4) + '</pre>');
From Array#forEach
The range of elements processed by forEach() is set before the first invocation of callback. Elements that are appended to the array after the call to forEach() begins will not be visited by callback. If the values of existing elements of the array are changed, the value passed to callback will be the value at the time forEach() visits them; elements that are deleted before being visited are not visited.
obj.forEach(function(user, index){
var userName = user.name;
//console.log(index, userName);
if(user.index === 5 || user.index === 2){
this.splice(index, 1);
}
}.bind(obj));
Here is the working fiddle
forEach is rather meant for so-called side-effects.
The problem with your code is, that you are changing the array while you are iterating over it. So if you remove one item, all the other indices of the array are reassigned immediately. That's why after removing one item, further removals don't do the desired thing (at the desired position).
So forEach is good for effecting things that are outside the actual array, that is iterated.
This would be a perfect usecase for a function called filter, since that's actually, what you are doing with your list: you want to filter out some items.
array = array.filter(function(item, index) {
return (index !== 5 && index !== 2)
}
Filter excepts a function as an argument, which itself will be called for each item in the array. If the function returns true for an item, it's kept - otherwise removed. That's why the logical expression must be slightly changed here: It reads like: Keep the items, which are not of index 5 and not of index 2. These sort of true-or-false returning functionas are called predicates.
What if you want to filter out some more indices? The expression using locical operators bees quickly quite long.
You can instead use the array method indexOf on a list of indices, passing each time the current index of your array to it. Either this will return the a position or -1 if it's not in it. In the later case you want to keep the item in the array.
array = array.filter(function(item, current_index) {
return ([2, 5].indexOf(current_index) === -1)
}
Also, you could wrap that in a function:
function removeIndices(array, indices) {
return array.filter(function(item, current_index) {
return (indices.indexOf(current_index) === -1)
})
}
Finally:
array = removeIndices(array, [2, 5]);