2016-06-16 25 views
7
var myArray = [1,2,3,4,5,6,7,8,9]; 

function isOdd(value){ 
    return value % 2; 
} 

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

Il codice sopra prende una matrice di lunghezza arbitraria e controlla ciascun valore. Se il valore del bit dell'array soddisfa una condizione arbitraria (in questo caso se è dispari), viene rimosso dall'array.Durante il looping dei valori di un array JS e rimuovo il valore, devo usare mentre invece di?

Array.prototype.splice() viene utilizzato per rimuovere il valore dall'array e quindi i viene decrementato per tenere conto del resto dei valori nell'array "moving down" per riempire lo spazio vuoto lasciato dal valore rimosso (quindi il ciclo non 'salta su un valore).

Tuttavia, il ciclo for termina quando i corrisponde alla lunghezza dell'array, che diventa più breve man mano che i valori vengono rimossi.

Il valore di myArray.length diminuisce dinamicamente come procede il ciclo, o salva il valore all'inizio del ciclo e non si aggiorna quando i valori vengono rimossi? Se quest'ultimo, cosa posso fare per risolvere il mio ciclo?

Grazie!

risposta

3

myArray.length sta cambiando con l'operazione sull'array. Ma il looping e lo splicing portano a risultati indesiderati, se non adeguatamente imbottiti.

Per evitare correzioni non necessarie, utilizzare un ciclo while dalla fine per mantenere il resto dell'array per l'elaborazione.

function isOdd(value) { 
 
    return value % 2; 
 
} 
 

 
var myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9], 
 
    i = myArray.length; 
 

 
while (i--) { 
 
    if (isOdd(myArray[i])) { 
 
     myArray.splice(i, 1); 
 
    } 
 
} 
 
console.log(myArray);

+0

Suggerirei che il metodo 'Array.prototype.filter()' di ordine superiore è la scelta migliore per questo tipo di operazione. Il codice dipendente dal metodo 'filter()' è considerevolmente più conciso e, direi, considerevolmente più leggibile. – Tex

+0

hai ragione, ma il problema è uno con la giuntura, e gli svantaggi di esso con il ciclo. –

+0

@Tex - '.filter()' è sicuramente più facile da usare, ma crea una nuova matrice piuttosto che modificare l'array originale che non è la stessa implementazione dell'OP. A volte, se un altro codice ha un riferimento a questo array, si desidera modificare l'array piuttosto che sostituirlo con uno nuovo. – jfriend00

0

La proprietà length viene letta in ogni iterazione e il metodo di giunzione aggiorna il suo valore, quindi funziona come ci si aspetterebbe. Tuttavia, direi che questa non è una buona pratica di codifica, un ciclo while è molto più leggibile, quindi dovrebbe essere la scelta più ovvia.

Per rispondere alla domanda direttamente: si non c'è bisogno di uso while invece di for, ma è sicuramente dovrebbe.

0

Usa Array.filter invece

var myArray = [1,2,3,4,5,6,7,8,9]; 
 
myArray=myArray.filter(function(item,index) { 
 
return !(item % 2); 
 
}) 
 

 
console.log(myArray)

0

Questo è dove ci si vuole utilizzare Array.prototype.filter() se non assolutamente necessario modificare l'originale array, sul posto.

Come sospetti, la proprietà .length dell'array viene aggiornata ogni volta che si splice(). Il metodo filter() è stato creato esattamente per questo tipo di operazione.

var myArray = [1,2,3,4,5,6,7,8,9]; 
 

 
function isOdd(value){ 
 
    return value % 2; 
 
} 
 

 
var filteredArray = myArray.filter(function(item){ 
 
    return !isOdd(item); 
 
}); 
 
    
 
console.log(filteredArray);

Una versione più concisa del codice di cui sopra:

var myArray = [1,2,3,4,5,6,7,8,9]; 
 

 
function isEven(value){ 
 
    return value % 2 === 0; 
 
} 
 
    
 
var filteredArray = myArray.filter(isEven); 
 

 
console.log(filteredArray);

una versione ancora più conciso basandosi su sintassi freccia ES6:

var myArray = [1,2,3,4,5,6,7,8,9]; 
 

 
var isEven = value => value % 2 === 0; 
 
    
 
var filteredArray = myArray.filter(isEven); 
 

 
console.log(filteredArray);

E, nel caso in cui è assolutamente necessario modificare la matrice in-place/utilizzare splice() qui, mi consiglia di utilizzare Array.prototype.forEach() nel corso di un ciclo for o while. forEach() è un altro metodo di ordine superiore che consente di realizzare la stessa funzionalità con un numero minore di piastre. Come con la maggior parte dei metodi/funzioni di ordine superiore, consente di concentrarsi sulla definizione di ciò che è necessario fare piuttosto che su come esattamente deve essere fatto.

var myArray = [1,2,3,4,5,6,7,8,9]; 
 

 
function isOdd(value){ 
 
    return value % 2; 
 
} 
 

 
myArray.forEach(function(c, i, a){ 
 
    if(isOdd(c)){ 
 
     a.splice(i,1); 
 
    } 
 
}) 
 

 
console.log(myArray);

0

È possibile utilizzare entrambi ed è dipende da quale gradite. se si preferisce utilizzare while loop poi Nina answer sembra buono e se si desidera utilizzare for loop quindi prendere in considerazione per gestire le modifiche del contatore da soli completamente o quando i cambiamenti di lunghezza:

function isOdd(value) { 
 
    return value % 2; 
 
} 
 

 
var arr1 = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 
 

 
for (var i = 0; i < arr1.length;) 
 
    isOdd(arr1[i]) ? arr1.splice(i, 1) : i++; 
 
console.log(arr1); 
 

 
var arr2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 
 

 
for (var i = 0; i < arr2.length; i++) 
 
    if (isOdd(arr2[i])) { 
 
    arr2.splice(i, 1); 
 
    i--; 
 
    } 
 
console.log(arr2);

Problemi correlati