2013-05-03 35 views
47

Mam szereg elementów i trzeba usunąć z nich pewne. Problem w tym, że JavaScript wydaje się nie mieć dla każdej pętli i jeśli używam pętli for, napotykam na problemy z tym, że zasadniczo próbuję sprawdzić elementy poza granicami tablicy lub brakujące elementy w tablicy, ponieważ zmieniają się indeksy . Pokażę ci, co mam na myśli:Jak iterować po tablicy i usunąć elementy w JavaScript

var elements = [1, 5, 5, 3, 5, 2, 4]; 
for(var i = 0; i < elements.length; i++){ 
    if(elements[i] == 5){ 
     elements.splice(i, 1); 
    } 
} 

Problem polega na tym, że gdy elementy [1] jest usuwany, elementy [2] staje elementów [1]. Pierwszym problemem jest to, że niektóre elementy nigdy nie są badane. Innym problemem jest to, że zmiany długości i jeśli mocno zakodowuję granice, to mogę próbować badać elementy poza granicami tablicy. Więc jaki jest najlepszy sposób na zrobienie tego niewiarygodnie prostego?

+1

'elements.splice (ja--, 1);' –

+0

nie lubię "-" lub "++" składnia ale przydatna wskazówka przy rozpoczynaniu od początku tablicy +1 – Xotic750

+0

Zobacz też: [Przechodzenie przez macierz i usuwanie elementów, bez przerywania pętli] (http://stackoverflow.com/q/9882284/1591669) – unor

Odpowiedz

125

Zacznij od góry!

var elements = [1, 5, 5, 3, 5, 2, 4]; 
for(var i = elements.length -1; i >= 0 ; i--){ 
    if(elements[i] == 5){ 
     elements.splice(i, 1); 
    } 
} 
+1

+1 dla gwiazda od końca, aby uniknąć przeskakiwania elementów ze względu na zmianę długości, o której wspomniał PO. – Xotic750

+9

'for (var i = elements.length; i -;)' jest prawdopodobnie najczęstszym sposobem zapisu. –

+0

@Dagg Nabbit, jedną rzeczą do zapamiętania z tym skrótem jest to, że spowoduje to błędy w jslint, jeśli powinieneś użyć takiego narzędzia do statycznej analizy kodu (i oczywiście "-"). – Xotic750

21

można użyć metody tutaj filter:

var elements = [1, 5, 5, 3, 5, 2, 4].filter(function(a){return a !== 5;}); 
//=> elements now [1,3,2,4] 

Albo, jeśli nie chce się dotknąć elements:

var elementsfiltered 
    ,elements = [1, 5, 5, 3, 5, 2, 4] 
       .filter(function(a){if (a!==5) this.push(a); return true;}, 
         elementsfiltered = []); 
    //=> elementsfiltered = [1,3,2,4], elements = [1, 5, 5, 3, 5, 2, 4] 

Zobacz MDN documentation dla filter

Alternatywnie cię może przedłużyć Array.prototype

Array.prototype.remove = Array.prototype.remove || function(val){ 
    var i = this.length; 
    while(i--){ 
     if (this[i] === val){ 
      this.splice(i,1); 
     } 
    } 
}; 
var elements = [1, 5, 5, 3, 5, 2, 4]; 
elements.remove(5); 
//=> elements now [1,3,2,4] 
+1

Podczas tworzenia nowej tablicy, która ma filtr, nie jest złym sugestią jako rozwiązaniem, OP faktycznie pyta o usuwanie elementów w linii i najlepiej byłoby dać przykład tego. – Xotic750

+1

Wygląda na niepotrzebne odejście od oryginalnego kodu. OP mógł zachować swój istniejący kod, zmniejszając wartość "i" po splice. –

+0

osobiście uważam, że filtr jest bezpieczniejszy ze względu na dekrementację i mogę prowadzić do przypadków skrajnych, tak jakby były tam zerowe elementy, itp. –

0

Jest to przykład zastosowania Array.indexOf, while i Array.splice usunąć elementy liniowe.

var elements = [1, 5, 5, 3, 5, 2, 4]; 
var remove = 5; 
var index = elements.indexOf(remove); 

while (index !== -1) { 
    elements.splice(index, 1); 
    index = elements.indexOf(remove); 
} 

console.log(elements); 

Na jsfiddle

+0

obniżony dla nieefektywnego algorytmu O (n^2) – Alnitak

+0

Nigdy nie wysuwałem żadnych roszczeń co do wydajności, a pytanie nie dotyczyło tego , ale jak radzić sobie ze zmieniającą się długością tablicy podczas usuwania elementu śródliniowego. Oto jsPerf, dzięki któremu możesz podać swoją skuteczną wersję jako odpowiedź i porównać ją z innymi opublikowanymi odpowiedziami. http://jsperf.com/soq-iterate-over-an-array-and-remove – Xotic750

+0

Kanoniczna metoda radzenia sobie ze zmieniającą się długością tablicy to rozpoczęcie od końca tablicy i praca wstecz. Ewentualnie możesz pracować do przodu _z aktualnej pozycji_ i nie zwiększać, jeśli usunąłeś bieżący element. Zamiast tego, twoja metoda _startuje z zerowego elementu_ za każdym razem, gdy znaleziono dopasowanie, a więc wielokrotnie przechodzi przez te same elementy. Jest to bardzo słaby algorytm i nigdy nie powinien być używany. – Alnitak

1

Korzystanie Array.shift():

var array = [1, 2, 3, 'a', 'b', 'c']; 
while (array.length > 0) { 
    console.log(array.shift()); 
} 

Edit: Prawdopodobnie nie pasuje specyfikacje. I misread pytanie (tylko usunąć pewne elementy) i był zbyt chętny zamiast dodać metodę, który nie został jeszcze wymieniony ...

+1

Tak jak mówisz w swojej edycji, nie odpowiada to na pytanie, ale odpowiada na pytanie, które próbowałem wyszukać. Dziękuję Ci. – spikyjt

1

Można po prostu zmniejszamy i w dowolnym momencie usunąć element.

var elements = [1, 5, 5, 3, 5, 2, 4]; 
 

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

 
console.log(elements);

2

var elements = [1, 5, 5, 3, 5, 2, 4];  
 
var i = elements.length; 
 
while (i--) { 
 
    if (elements[i] == 5) { 
 
     elements.splice(i, 1); 
 
    } 
 
} 
 
console.log(elements);

+1

Pod względem czytelności kodu odpowiedź jest urocza –