Recorriendo la matriz y eliminando elementos, sin romper el bucle

Resuelto dzm asked hace 12 años • 18 respuestas

Tengo el siguiente bucle for, y cuando lo uso splice()para eliminar un elemento, obtengo que "segundos" no está definido. Podría comprobar si no está definido, pero creo que probablemente haya una forma más elegante de hacerlo. El deseo es simplemente eliminar un elemento y continuar.

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);
    }           
}
dzm avatar Mar 27 '12 08:03 dzm
Aceptado

La matriz se vuelve a indexar cuando realiza un .splice(), lo que significa que omitirá un índice cuando se elimine uno y su caché .lengthquedará obsoleto.

Para solucionarlo, necesitaría disminuir idespués de a .splice()o simplemente iterar en reversa...

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

De esta manera, la reindexación no afecta el siguiente elemento de la iteración, ya que la indexación afecta solo a los elementos desde el punto actual hasta el final de la matriz, y el siguiente elemento de la iteración es inferior al punto actual.

 avatar Mar 27 '2012 01:03

Este es un problema bastante común. La solución es hacer un bucle hacia atrás:

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

No importa si los sacas del final porque los índices se conservarán a medida que retrocedas.

frattaro avatar Jan 24 '2015 03:01 frattaro

Vuelva a calcular la longitud cada vez que recorra el bucle en lugar de hacerlo solo al principio, por ejemplo:

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
      }
}

De esa manera no excederás los límites.

EDITAR: agregó una disminución en la declaración if.

Marc avatar Mar 27 '2012 01:03 Marc