By dzm

2012-03-27 01:44:07 8 Comments

I have the following for loop, and when I use splice() to remove an item, I then get that 'seconds' is undefined. I could check if it's undefined, but I feel there's probably a more elegant way to do this. The desire is to simply delete an item and keep on going.

for (i = 0, len = Auction.auctions.length; i < len; i++) {
    auction = Auction.auctions[i];
    Auction.auctions[i]['seconds'] --;
    if (auction.seconds < 0) { 
        Auction.auctions.splice(i, 1);


@Bhanuprakash D 2018-11-06 16:24:54

There are lot of wonderful answers on this thread already. However I wanted to share my experience when I tried to solve "remove nth element from array" in ES5 context.

JavaScript arrays have different methods to add/remove elements from start or end. These are:

arr.push(ele) - To add element(s) at the end of the array 
arr.unshift(ele) - To add element(s) at the beginning of the array
arr.pop() - To remove last element from the array 
arr.shift() - To remove first element from the array 

Essentially none of the above methods can be used directly to remove nth element from the array.

A fact worth noting is that this is in contrast with java iterator's using which it is possible to remove nth element for a collection while iterating.

This essentially leaves us with only one array method Array.splice to perform removal of nth element (there are other things you could do with these methods as well, but in the context of this question I am focusing on removal of elements):

Array.splice(index,1) - removes the element at the index 

Here is the code copied from original answer (with comments):

var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length 

while (i--) //decrement counter else it would run into IndexOutBounds exception
  if (arr[i] === "four" || arr[i] === "two") {
    //splice modifies the original array
    arr.splice(i, 1); //never runs into IndexOutBounds exception 
    console.log("Element removed. arr: ");

  } else {
    console.log("Element not removed. arr: ");

Another noteworthy method is Array.slice. However the return type of this method is the removed elements. Also this doesn't modify original array. Modified code snippet as follows:

var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length 

while (i--) //decrement counter 
  if (arr[i] === "four" || arr[i] === "two") {
    console.log("Element removed. arr: ");
    console.log(arr.slice(i, i + 1));
    console.log("Original array: ");

Having said that, we can still use Array.slice to remove nth element in the following way and as you can observe it is lot more code (hence inefficient)

var arr = ["one", "two", "three", "four"];
var i = arr.length; //initialize counter to array length 

while (i--) //decrement counter 
  if (arr[i] === "four" || arr[i] === "two") {
    console.log("Array after removal of ith element: ");
    arr = arr.slice(0, i).concat(arr.slice(i + 1));


The Array.slice method is extremely important to achieve immutability in functional programming à la redux

@0xc0de 2013-09-06 08:01:50

Although your question is about deleting elements from the array being iterated upon and not about removing elements (in addition to some other processing) efficiently, I think one should reconsider it if in similar situation.

The algorithmic complexity of this approach is O(n^2) as splice function and the for loop both iterate over the array (splice function shifts all elements of array in the worst case). Instead you can just push the required elements to the new array and then just assign that array to the desired variable (which was just iterated upon).

var newArray = [];
for (var i = 0, len = Auction.auctions.length; i < len; i++) {
    auction = Auction.auctions[i];
    if (!auction.seconds < 0) { 
Auction.auctions = newArray;

Since ES2015 we can use Array.prototype.filter to fit it all in one line:

Auction.auctions = Auction.auctions.filter(auction => --auction.seconds >= 0);

@Alexis Wilke 2014-05-24 04:55:08

I thinks your method is the safest, as it creates a new array we do not have to worry about the for() index to "break". With newer browsers, though we can use the Array.filter() function instead:…

@user1115652 2015-01-04 20:44:05

note that the filter version here doesn't decrement the seconds on every auction like the for loop version!

@qxz 2016-11-24 03:51:03

Does anyone have a benchmark on using filter vs. iterating backwards + splice?

@emanuel.virca 2017-04-06 14:38:01

Filter works for me.

@whitneyland 2017-12-01 11:52:50

Updated to use an arrow: auctions = auctions.filter(auction => --auction.seconds >=0) now whole thing fits on one line and the browser compatibility is good in 2017.

@0xc0de 2018-09-26 15:07:26

@dhilt Can you explain the reason of your edit to remove that code? I've not been able to keep up with ES recently, has anything changed?

@dhilt 2018-09-26 16:28:51

@0xc0de I walked through the answer revisions and compiled a new version of the update related to filter based on your pre-pre-revision that seems more suitable that the Lee's pre-revision. Sorry, if I'm making you uncomfortable.

@0xc0de 2018-09-26 16:46:51

@dhilt No worries, I was just wondering if something has changed since. Thanks for your efforts to improve/keep up-to-date this answer.

@user1106925 2012-03-27 01:50:52

The array is being re-indexed when you do a .splice(), which means you'll skip over an index when one is removed, and your cached .length is obsolete.

To fix it, you'd either need to decrement i after a .splice(), or simply iterate in reverse...

var i = Auction.auctions.length
while (i--) {
    if (...) { 
        Auction.auctions.splice(i, 1);

This way the re-indexing doesn't affect the next item in the iteration, since the indexing affects only the items from the current point to the end of the Array, and the next item in the iteration is lower than the current point.

@Dmitry Pashkevich 2012-10-25 13:08:51

Looks like the best solution to me. And the fastest one, by the way.

@0xc0de 2013-09-06 07:10:43

Nice! Why is this a community wiki btw?

@Darius 2013-09-30 13:04:55

Out of interest, this solution in its current guise presumably wont work if the array was an array of functions that you wanted to iterate over and invoke in the order that they were added to the array, for example?

@thedjaney 2014-09-16 02:48:40

i do mine by incrementing only if there is no delete

@ptf 2014-12-10 09:42:40

When you remove an entry from the array, then the next item you'll iterate over will be the same item as you are currently iteration over. Just something to keep in mind. And if you remove more than one item per iteration, you'll have to adjust len, else it will be out of bounds.

@super 2016-06-06 18:39:12

Pro tip: Never forget this solution

@frattaro 2017-04-02 12:55:44

Don't forget to break yourself out of the while loop when your iterator is less than zero.

@user1106925 2017-04-02 13:12:30

@frattaro: The condition will break the loop, at least in this case since the .length of an Array is never less than 0.

@frattaro 2017-04-02 13:27:45

@squint Oh, I see. the condition i-- will at some point return 0, and 0 will be evaluated to false. Neat.

@user1106925 2017-04-02 13:31:38

@frattaro: Yep, exactly. :)

@frattaro 2017-04-02 13:41:52

@squint I'd rather it was explicitly stated. Wouldn't use it in practice.

@user1106925 2017-04-02 13:45:57

@frattaro: Yeah it's one of those things that we see so often that we don't even think twice about it, but I agree that it isn't the clearest construct.

@Neon 2017-11-10 09:26:19

What was the reason for choosing a while loop over a for loop?

@Cruril 2017-11-30 22:18:36

@Neon Less code would be my guess. This solution is less than if you used a for loop for the same thing.

@3Dom 2018-02-14 03:47:30

var i = Auction.auctions.length - 1; (most folks will use this as the last(first) index to iterate over)

@Jake T. 2018-03-15 18:31:10

@3Dom the condition uses a post decrement, so say an array of length 5, it will look like while(5), which evaluates to true, 5 turns into 4, and 4 is used within the loop body as the index to get the next (first) item in the array, at the last index.

@Ryan Kopf 2018-05-14 13:52:06

I have never in my life seen someone iterate backwards over an array in Javascript like that, and it's the most brilliant thing I've ever seen. Why is this not more common.

@Rubinsh 2017-11-29 07:28:04

If you are e using ES6+ - why not just use Array.filter method?

Auction.auctions = Auction.auctions.filter((auction) => {
  auction['seconds'] --;
  return (auction.seconds > 0)

Note that modifying the array element during filter iteration only works for objects and will not work for array of primitive values.

@user8533067 2017-08-29 14:06:09

You can just look through and use shift()

@Ivan 2017-08-29 14:41:00

Please add an example using this method.

@Dmitry Ragozin 2016-12-15 15:33:46

for (i = 0, len = Auction.auctions.length; i < len; i++) {
    auction = Auction.auctions[i];
    Auction.auctions[i]['seconds'] --;
    if (auction.seconds < 0) {
        Auction.auctions.splice(i, 1);

@B001ᛦ 2016-12-15 15:53:44

A good answer will always have an explanation of what was done and why it was done in such a manner, not only for the OP but for future visitors to SO.

@Pablo 2016-11-17 16:40:28

Another simple solution to digest an array elements once:

    // From first to last...
    var auction = Auction.auctions.shift();
    // From last to first...
    var auction = Auction.auctions.pop();

    // Do stuff with auction

@daniel.szaniszlo 2016-02-26 12:34:38

Here is another example for the proper use of splice. This example is about to remove 'attribute' from 'array'.

for (var i = array.length; i--;) {
    if (array[i] === 'attribute') {
        array.splice(i, 1);

@Izzy 2017-11-13 10:49:43

shouldn't be that array.length-1 ?

@daniel.szaniszlo 2017-11-15 00:23:14

I think not because i-- reduces the index. If you do array.length-1 then the last element of array will be skipped

@Izzy 2017-11-15 11:53:50

Ah I see, but I must argue a bit that it is not so readable. Even tho I'm not beginner, at first glance I also didn't saw that inside check block of for loop you decrement i. for( var i = array.length-1; i>=0; i-- ) is much more cleaner (and it produces same effect)

@Zon 2016-01-28 15:54:43

Try to relay an array into newArray when looping:

var auctions = Auction.auctions;
var auctionIndex;
var auction;
var newAuctions = [];

for (
  auctionIndex = 0; 
  auctionIndex < Auction.auctions.length;
  auctionIndex++) {

  auction = auctions[auctionIndex];

  if (auction.seconds >= 0) { 

Auction.auctions = newAuctions;

@frattaro 2015-01-24 03:49:17

This is a pretty common issue. The solution is to loop backwards:

for (var i = Auction.auctions.length - 1; i >= 0; i--) {
    if (Auction.auctions[i].seconds < 0) { 
        Auction.auctions.splice(i, 1);

It doesn't matter if you're popping them off of the end because the indices will be preserved as you go backwards.

@Aesthete 2013-09-06 08:12:44 = Auction.auctions.filter(function(el) {
  return --el["seconds"] > 0;

@Alexis Wilke 2014-05-24 04:17:57

This is a cool method, similar to 0xc0de above. Only problem, it was implemented in IE9+ only... so not backward compatible.

@Michael Scheper 2016-12-13 03:48:00

@AlexisWilke: Luckily, we're in the future now, and can dance on the graves of IE8 and its predecessors.

@Arashsoft 2018-11-14 21:09:02

I think the main issue is it breaks the reference to the array.

@Marc 2012-03-27 01:50:20

Recalculate the length each time through the loop instead of just at the outset, e.g.:

for (i = 0; i < Auction.auctions.length; i++) {
      auction = Auction.auctions[i];
      Auction.auctions[i]['seconds'] --;
      if (auction.seconds < 0) { 
          Auction.auctions.splice(i, 1);
          i--; //decrement

That way you won't exceed the bounds.

EDIT: added a decrement in the if statement.

@RobG 2012-03-27 02:08:29

I thnk it's easier to just go backwards through the array, then you don't need to adjust the length at all.

@Doug S 2012-10-27 05:40:20

I also overlooked recalculating the array length after splicing in a loop. Funny how something so simple can have us scratching our heads for a moment.

@chakeda 2018-11-21 21:25:43

@RobG I agree, but I would argue in some situations, you may need to loop forwards.

Related Questions

Sponsored Content

76 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 5491804 View
  • 6814 Score
  • 76 Answer
  • Tags:   javascript arrays

14 Answered Questions

[SOLVED] How to insert an item into an array at a specific index (JavaScript)?

39 Answered Questions

[SOLVED] Loop through an array in JavaScript

35 Answered Questions

[SOLVED] How do I loop through or enumerate a JavaScript object?

21 Answered Questions

[SOLVED] How to loop through a plain JavaScript object with the objects as members?

  • 2009-05-28 16:18:14
  • edt
  • 1398898 View
  • 1360 Score
  • 21 Answer
  • Tags:   javascript

31 Answered Questions

[SOLVED] How do I break out of nested loops in Java?

  • 2009-05-20 09:07:43
  • boutta
  • 1006508 View
  • 1635 Score
  • 31 Answer
  • Tags:   java loops

34 Answered Questions

[SOLVED] How to remove item from array by value?

  • 2010-10-17 17:43:34
  • MacMac
  • 786101 View
  • 717 Score
  • 34 Answer
  • Tags:   javascript arrays

11 Answered Questions

[SOLVED] Looping through the content of a file in Bash

  • 2009-10-05 17:52:54
  • Peter Mortensen
  • 1220010 View
  • 1069 Score
  • 11 Answer
  • Tags:   linux bash loops unix io

15 Answered Questions

[SOLVED] C# loop - break vs. continue

  • 2008-08-08 21:49:01
  • Seibar
  • 664580 View
  • 718 Score
  • 15 Answer
  • Tags:   c# loops enumeration

13 Answered Questions

[SOLVED] Is the recommendation to include CSS before JavaScript invalid?

Sponsored Content