2013-06-26 18 views
7

Ich frage mich, ob und was ist eine zuverlässige und/oder Standard-Art der Iteration eines Arrays, dessen Länge innerhalb der Schleife ändert. Ich frage, weil ich am Ende jedes Mal eine andere Methode wähle, um dies zu tun, z.Schleife durch Array beim Entfernen von Elementen

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

oder

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

Dies sind die Möglichkeiten, wie ich mir das finden zu tun, aber ich bin neugierig, ob es ein Standard-Ansatz.

+0

Haben Sie diese Option aktiviert [http://stackoverflow.com/questions/9882284/looping-through-array-and- Entfernen-Elemente-ohne-Break-for-Loop] Antwort? –

+1

Sie könnten Ihre Vorwärts-Iteration im ersten Beispiel behalten und Ihren Post-Dekrementieren 'i' direkt in den' .splice() 'Aufruf setzen:' myarray.splice (i--, 1); ' –

Antwort

22

finde ich einfacher in der anderen Richtung iterieren:

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

Auf diese Weise müssen Sie nicht den Zuwachs ändern, wenn entfernen.

Viele Entwickler, insbesondere diejenigen, die sich vor JavaScript nicht mit C-ähnlichen Sprachen beschäftigt haben, finden es verwirrend, mit den Feinheiten des Dekrement-Operators umzugehen. Die Schleife, die ich schrieb, kann auch geschrieben werden als

+0

das ist genial, danke –

+0

+1 Ich habe heute morgen eine ähnliche Frage in einem Interview gestellt ;-) Der beste Teil ist sogar, dass ich nicht an diese Lösung gedacht habe. –

+0

Dies ist definitiv empfohlene Methode, um durch eine Sammlung zu iterieren, bei der Elemente entfernt werden. Ich mache das in jeder Sprache. – jlafay

0

Wie auch immer Sie es tun, beginnend in umgekehrter Reihenfolge und Countdown ist am einfachsten. Es hängt auch davon ab, ob Ihr Array spärlich ist und ob es sparsam sein soll. Am einfachsten ist es, sich selbst eine wiederverwendbare Funktion und eine eigene Bibliothek zu erstellen. Du könntest das tun. Wenn Sie compress auf true setzen, wird Ihr Array zu einem kontinuierlichen und nicht zu einem spärlichen Array. Diese Funktion entfernt alle übereinstimmenden Vorkommen des Werts und gibt ein Array der entfernten Elemente zurück.

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); 

Ausgabe

[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] 

Auf jsfiddle

Verwandte Themen