2013-06-26 13 views
7

Mi chiedo se e quale sia un modo affidabile e/o standard per iterare una matrice la cui lunghezza sta cambiando all'interno del ciclo. Chiedo perché alla fine scelgo un metodo diverso per farlo ogni volta che voglio farlo, ad es.Loop through array durante la rimozione degli elementi

for (var i = 0; i < myarray.length; i++) { 
    if (myarray[i] === 'something') { 
    myarray.splice(i, 1); 

    // *to avoid jumping over an element whose index was just shifted back to the current i 
    i--; 
    } 
} 

o

var i = 0; 
while (myarray[i]) { 
    if (myarray[i] === 'something') { 
    myarray.splice(i, 1); 
    } else { 
    i++; 
    } 
} 

Questi sono i modi mi ritrovo a fare questo, ma io sono curioso di sapere se v'è un approccio standard.

+0

Sono state prese questo [http://stackoverflow.com/questions/9882284/looping-through-array-and- remove-items-without-breaking-for-loop] risposta? –

+1

Puoi mantenere la tua iterazione diretta nel primo esempio e mettere il tuo decrementare 'i' direttamente nella chiamata' .splice() ':' myarray.splice (i--, 1); ' –

risposta

22

trovo più semplice per scorrere nella direzione opposta:

for (var i=myarray.length; i--;) { 
    if (myarray[i] === 'something') myarray.splice(i, 1); 
} 

In questo modo non c'è bisogno di modificare l'incremento durante la rimozione.

Molti sviluppatori, in particolare quelli che non avevano a che fare con linguaggi di tipo C prima di JavaScript, lo trovano confuso nell'affrontare le sottigliezze dell'operatore di decremento. L'anello che ho scritto può anche essere scritta come

for (var i=myarray.length-1; i>=0; i--) { 
+0

questo è fantastico, grazie –

+0

+1 Ho fatto una domanda simile in un'intervista stamattina ;-) La parte migliore è anche che non ho pensato a questa soluzione –

+0

Questo è decisamente un modo consigliato per scorrere una collezione che avrà gli elementi rimossi. Lo faccio in qualsiasi lingua – jlafay

0

Tuttavia si sceglie di farlo, a partire in retromarcia e il conto alla rovescia è più semplice. Dipende anche dal fatto che il tuo array sia scarso e se desideri che rimanga scarso. La cosa più semplice è crearti una funzione riutilizzabile e la tua libreria personale. Potresti farlo Se si imposta compress su true, la matrice diventerà una matrice continua anziché sparsa. Questa funzione rimuoverà tutte le occorrenze corrispondenti del valore e restituirà un array degli elementi rimossi.

Javascript

function is(x, y) { 
    if (x === y) { 
     if (x === 0) { 
      return 1/x === 1/y; 
     } 

     return true; 
    } 

    var x1 = x, 
     y1 = y; 

    return x !== x1 && y !== y1; 
} 

function removeMatching(array, value /*, compress (default = false)*/) { 
    var removed = [], 
     compress = arguments[2], 
     index, 
     temp, 
     length; 

    if (typeof compress !== "boolean") { 
     compress = false; 
    } 

    if (compress) { 
     temp = []; 
     length = array.length; 
     index = 0; 
     while (index < length) { 
      if (array.hasOwnProperty(index)) { 
       temp.push(array[index]); 
      } 

      index += 1; 
     } 
    } else { 
     temp = array; 
    } 

    index = 0; 
    length = temp.length; 
    while (index < length) { 
     if (temp.hasOwnProperty(index) && is(temp[index], value)) { 
      if (compress) { 
       removed.push(temp.splice(index, 1)[0]); 
      } else { 
       removed.push(temp[index]); 
       delete temp[index]; 
      } 
     } 

     index += 1; 
    } 

    if (compress) { 
     array.length = 0; 
     index = 0; 
     length = temp.length; 
     while (index < length) { 
      if (temp.hasOwnProperty(index)) { 
       array.push(temp[index]); 
      } 

      index += 1; 
     } 
    } 

    return removed; 
} 

var test = []; 

test[1] = 1; 
test[50] = 2; 
test[100] = NaN; 
test[101] = NaN; 
test[102] = NaN; 
test[200] = null; 
test[300] = undefined; 
test[400] = Infinity; 
test[450] = NaN; 
test[500] = -Infinity; 
test[1000] = 3; 

console.log(test); 
console.log(removeMatching(test, NaN)); 
console.log(test); 
console.log(removeMatching(test, Infinity, true)); 
console.log(test); 

uscita

[1: 1, 50: 2, 100: NaN, 101: NaN, 102: NaN, 200: null, 300: undefined, 400: Infinity, 450: NaN, 500: -Infinity, 1000: 3] 
[NaN, NaN, NaN, NaN] 
[1: 1, 50: 2, 200: null, 300: undefined, 400: Infinity, 500: -Infinity, 1000: 3] 
[Infinity] 
[1, 2, null, undefined, -Infinity, 3] 

Su jsfiddle

Problemi correlati