34
var people = ['alex','jason','matt'];

people.forEach(function(p){
    if(p.length > 4){
       //REMOVE THIS PERSON or pop it out of the list or whatever
    }
});

console.log(people) //should return ['alex','matt']

I want to remove an element out of the list, using this forEach loop.

TIMEX
  • 259,804
  • 351
  • 777
  • 1,080
  • 1
    I don't believe you're supposed to modify a list as you loop over it. – Rafe Kettler Aug 05 '11 at 00:44
  • 2
    What have you tried? SO is (essentially) for problems; it is not a classroom. – Lightness Races in Orbit Aug 05 '11 at 00:45
  • 2
    I second Rafe and Tomalak's comments. To expand on what Rafe said: it's not normal practice to remove elements inside a for each loop (though I'm not sure how JavaScript handles it; maybe it'll work). You're (almost certainly) better off using a standard index-based for loop; I suggest looping backwards from the last element so that you can remove elements without having to adjust the index variable. Have a look at the [MDN Array doco](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array) for details on Array's methods. – nnnnnn Aug 05 '11 at 01:06

5 Answers5

62

Use the right tools for the right job. In this case:

for (var i = 0; i < data.length; i++) {
    if (data[i].value === 5) {
        data.splice(i--, 1);
    }
}

or as @nnnnnn has suggested, loop backwards:

for (var i = data.length-1; i >= 0; i--) {
    if (data[i].value === 5) {
        data.splice(i, 1);
    }
}

However, you should consider using Array.prototype.filter():

data = data.filter(function (e) {
    return e.value !== 5;
});

or a utility function library such as lodash or underscore, which provide a function for removing elements from an array:

_.remove(data, function (e) {
    return e.value === 5;
});

The benefit of the latter two is that your code becomes more readable.

Kip
  • 107,154
  • 87
  • 232
  • 265
Gajus
  • 69,002
  • 70
  • 275
  • 438
  • 4
    This is a neat solution that considers the issues of changing indecies! – carl-johan.blomqvist Jan 27 '13 at 12:51
  • 3
    `.filter` looks really nice – Luca Steeb Nov 15 '15 at 11:56
  • @Gajus FYI `.filter()` does not modify the array, it returns a new array. I've made an edit to reflect this. You might also want to update with shorter ES6 syntax- `data = data.filter(e => e.value !== 5);` – Kip Mar 11 '19 at 17:37
  • A backward for-loop is very efficient and is the most legible procedure that's suitable for dealing with a large dataset that you don't want to copy and clobber. – Jeff McMahan Apr 04 '23 at 14:35
32

You shouldn't modify the array you're looping on. You can produce a new one, though:

var newPeople = [];
people.forEach(function(p){
    if(p.length <= 4){
        newPeople.push(p);
    }
});

Why you shouldn't modify array you're looping.

mhpreiman
  • 139
  • 2
  • 4
  • 13
Mrchief
  • 75,126
  • 20
  • 142
  • 189
  • 6
    You can modify the array in the callback function provided to *forEach*, there is nothing in ES5 to say you can't. – RobG Aug 05 '11 at 01:03
  • @Hans Engel - why `<=`? the OP is `< 4`. @Mrchief - the OP is `I want to remove an element out of the list` so I presume the intention is to modify the array (as do most Array methods). – RobG Aug 05 '11 at 01:13
  • @RobG, the OP was `> 4` - The complement of `>` is `<=`. – Jon Gauthier Aug 05 '11 at 02:20
1

ForEach, since ES5 can be used together with an index:

data.forEach(function (element, index) {
  if (element % 2 == 0) {
    data.splice(index, 1);
  }
});
adripanico
  • 1,026
  • 14
  • 32
  • 3
    Note that this code snippet *doesn't actually work* -- if data is `[1,28,35,444,555,666,333,424,313,303,484,464,121,12,14,88,96,108,1224,777]` then this will turn it to `[1, 35, 555, 333, 313, 303, 464, 121, 14, 96, 1224, 777]` – Jessica Knight Apr 28 '17 at 02:43
  • 2
    This is true and it is easy to see why and so why forEach is not the correct approach for this task as @Gajus explained. In your example, when we remove item with index 1 (value 28), the next element to be analyzed is index 2, which should be the value 35 but it is now the value 444, so 35 is skipped. And so on... – adripanico Apr 24 '19 at 07:34
1

You can do this very easily with filter():

var people = ['alex','jason','matt'];

var shortPeople = people.filter(function(p){
    return p.length <= 4);
});

console.log(people);
console.log(shortPeople);
Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
0

Use Array.prototype.filter instead

const filterByLength = (arr, len) => arr.filter(s => s.length <= len);

const people = ["jon", "alex", "jason", "matt"];
console.log(filterByLength(people, 4)); // ["jon", "alex", "matt"]
Roko C. Buljan
  • 196,159
  • 39
  • 305
  • 313