Javascript - Array-Element unter der Bedingung entfernen

77

Ich habe mich gefragt, wie ich eine Methode in Javascript implementieren soll, die alle Elemente eines Arrays entfernt, die eine bestimmte Bedingung löschen. (Am besten ohne jQuery)

Ex.

ar = [ 1, 2, 3, 4 ];
ar.removeIf( function(item, idx) {
    return item > 3;
});

Das Obige würde jedes Element im Array durchgehen und alle Elemente return truefür die Bedingung entfernen (im Beispiel Element> 3).

Ich fange gerade mit Javascript an und habe mich gefragt, ob jemand einen kurzen, effizienten Weg kennt, um dies zu erreichen.

- Update -

Es wäre auch großartig, wenn die Bedingung auch für Objekteigenschaften funktionieren könnte.

Ex.

ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
ar.removeIf( function(item, idx) {
    return item.str == "c";
});

Wo würde der Artikel entfernt werden, wenn item.str == "c"

- update2 -

Es wäre schön, wenn auch die Indexbedingungen funktionieren könnten.

Ex.

ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
ar.removeIf( function(item, idx) {
    return idx == 2;
});
dk123
quelle

Antworten:

48

Sie können Ihre eigene Methode hinzufügen Array, um etwas Ähnliches zu tun, wenn filterdies für Sie nicht funktioniert.

Array.prototype.removeIf = function(callback) {
    var i = 0;
    while (i < this.length) {
        if (callback(this[i], i)) {
            this.splice(i, 1);
        }
        else {
            ++i;
        }
    }
};

Für mich ist das eine der coolsten Funktionen von JavaScript. Ian wies auf einen effizienteren Weg hin, um dasselbe zu tun. In Anbetracht dessen, dass es sich um JavaScript handelt, hilft jedes Bit:

Array.prototype.removeIf = function(callback) {
    var i = this.length;
    while (i--) {
        if (callback(this[i], i)) {
            this.splice(i, 1);
        }
    }
};

Auf diese Weise müssen Sie sich nicht einmal Gedanken über das Aktualisieren lengthoder Abfangen des nächsten Elements machen, da Sie sich eher nach links als nach rechts arbeiten.

pickypg
quelle
Danke, funktioniert super. Mir gefällt, wie dies berücksichtigt, dass sich der Index während der Iteration durch Spleißen ändert.
dk123
4
Das ist ein bisschen chaotisch. Versuchen Sie es mit jsfiddle.net/n8JEy/4 - und Sie haben iden Rückruf nicht als zweiten Parameter übergeben
Ian
@ Ian Ich bevorzuge eher die Lesbarkeit, aber Ihre Lösung ist sicherlich effizienter. Ich habe auch den Index als zweiten Parameter hinzugefügt (habe ihn ursprünglich einfach ignoriert, da er nicht verwendet wurde, und ich habe angenommen, dass er ihn nicht benötigt).
Pickypg
@ dk123 Als Neuling in JavaScript können Sie die Parameter solcher Rückrufe nach Belieben steuern und sie beliebig hinzufügen, solange die Informationen verfügbar sind (z. B. können Sie die Länge des aktuellen Arrays mithilfe von hinzufügen this.lengthals dritter Parameter, wenn Sie eine Neigung hatten).
Pickypg
@pickypg Kein Problem! Das stimmt definitiv. Ich glaube, ich habe keinen Grund gesehen, die Logik so zu trennen, aber es ist eindeutig in Ordnung. Und "chaotisch" war der falsche Begriff. Ich wusste nichts über den zweiten Parameter, wollte ihn aber nur darauf hinweisen :)
Ian
91

Sie können die Array-Filtermethode verwenden .

Der Code würde folgendermaßen aussehen:

ar = [1, 2, 3, 4];
ar = ar.filter(item => !(item > 3));
console.log(ar) // [1, 2, 3]

Klaster_1
quelle
41
Wenn Sie !(item > 3)in die menschliche Sprache übersetzen, wird es sein item <= 3.
Miha_x64
4
Beachten Sie, dass die Array.filter-Methode ein neues Array erstellt. Wenn Sie Ihr Array in einer anderen Variablen referenzieren, wird die Referenz anschließend unterbrochen: ar1 = [1, 2, 3, 4]; ar2 = ar1; ar1 = ar1.filter(item => !(item > 3)); console.log(ar1); console.log(ar2);
Atilla Baspinar
36

Sie können verwenden Array.filter(), was das Gegenteil bewirkt:

ar.filter(function(item, idx) {
    return item <= 3;
});
Mixer
quelle
2
Als Heads-up wird das in IE8 oder niedriger nicht unterstützt. Sie sollten auch entweder den ursprünglichen Ausdruck negieren oder es sollte sein <=.
Pickypg
16
Gibt Array.filter () nicht ein neues Array mit den gefilterten Elementen zurück? Gibt es etwas, das nur die Elemente aus dem Array entfernt?
dk123
@ dk123: Es ist nichts vorgefertigt. Sie müssen eine forSchleife schreiben .,
Blender
Das Erstellen eines neuen Arrays mit Array.filterist wahrscheinlich schneller als das manuelle Ausspleißen des angegebenen Arrays.
Casey Chu
@Blender Das ist sehr interessant. Ich schwöre, ich habe mir kürzlich etwas angesehen, das die beiden vergleicht, und es war das Gegenteil. Dummer Kommentar von mir gelöscht. Vielen Dank für den Beweis :)
Ian
5

Sie können lodash.remove verwenden

var array = [1, 2, 3, 4];
var evens = _.remove(array, function(n) {
  return n % 2 == 0;
});

console.log(array);
// => [1, 3]

console.log(evens);
// => [2, 4]
Satoshi Suzuki
quelle
2

Ich liebe diese Art von Fragen und nur eine andere Version von mir ... :)

Array.prototype.removeIf = function(expression) {
   var res = [];
    for(var idx=0; idx<this.length; idx++)
    {
      var currentItem = this[idx];
        if(!expression(currentItem))
        {
            res.push(currentItem);
        }
    }
    return res;
}

ar = [ 1, 2, 3, 4 ];
var result = ar.removeIf(expCallBack);


console.log(result);
function expCallBack(item)
{
    return item > 3;
}
PSL
quelle
1
Könnten Sie vielleicht Ihren Code ein wenig ändern (oder eine andere Methode hinzufügen), um Elemente tatsächlich zu entfernen, anstatt ein neues Array zurückzugeben? Danke für die Antwort.
dk123
3
wer auch immer das so falsch herabgestimmt hat. Dies ist die beste Antwort von allen. Überprüfen Sie den Test unter @Blender jsperf.com/splice-vs-filter. Es ist mindestens 2x schneller und bis zu 15x schneller in den neuesten Versionen von Firefox
Parlament
2

Schreiben Sie einfach das folgende Beispiel, wenn die Bedingung auch für Objekteigenschaften funktionieren könnte

var ar = [ {num:1, str:"a"}, {num:2, str:"b"}, {num:3, str:"c"} ];
var newArray = [];
for (var i = 0, len = ar.length; i<len; i++) {
        if (ar[i].str == "b") 
        {newArray.push(ar[i]);};
 };
console.log(newArray);

Siehe das Beispiel Live-Beispiel

vamsikrishnamannem
quelle
2

Machen Sie es zu einem Einzeiler mit Pfeilfunktion:

ar = ar.filter(i => i > 3);
michal.jakubeczy
quelle