Frage

Ich möchte eine Reihe von Elementen mithilfe von filtern map() Funktion.Hier ist ein Codeausschnitt:

var filteredItems = items.map(function(item)
{
    if( ...some condition... )
    {
        return item;
    }
});

Das Problem ist, dass herausgefilterte Elemente immer noch Platz im Array beanspruchen und ich sie am liebsten komplett löschen würde.

Irgendeine Idee?

BEARBEITEN:Danke, das habe ich vergessen filter(), was ich wollte, ist eigentlich ein filter() dann ein map().

EDIT2:Danke für den Hinweis map() Und filter() sind nicht in allen Browsern implementiert, obwohl mein spezifischer Code nicht für die Ausführung in einem Browser gedacht war.

War es hilfreich?

Lösung

Sie sollten das verwenden filter Methode statt Map, es sei denn, Sie möchten zusätzlich zum Filtern die Elemente im Array ändern.

z.B.

var filteredItems = items.filter(function(item)
{
    return ...some condition...;
});

[Bearbeiten:Natürlich könnte man das immer tun sourceArray.filter(...).map(...) sowohl filtern als auch mutieren]

Andere Tipps

Ich habe vor einiger Zeit eine Antwort geschrieben und meine Meinung hat sich geändert.Ich empfehle einen Blick auf meine Blogeintrag Das erweitert dieses Thema und erklärt es viel besser.Außerdem gibt es am Ende der Alternativen einen JSperf-Vergleich.

Der Tl;dr ist dieser:Um das zu erreichen, was Sie verlangen (Filtern und Zuordnen innerhalb eines Funktionsaufrufs), sollten Sie verwenden Array.reduce().Allerdings ist die besser lesbar Und normalerweise schneller2 Der Ansatz besteht darin, Filter und Karte einfach miteinander zu verketten:

[1,2,3].filter(num => num > 2).map(num => num * 2)

Was folgt, ist eine Beschreibung, wie Array.reduce() funktioniert und wie es verwendet werden kann, um Filter und Zuordnung in einer Iteration durchzuführen.Wem das zu kurz ist, dem empfehle ich dringend, sich den oben verlinkten Blog-Beitrag anzusehen, der eine viel freundlichere Einführung mit klaren Beispielen und Fortschritten bietet.

Sie geben Reduce ein Argument an, das eine (normalerweise anonyme) Funktion ist.

Diese anonyme Funktion benötigt zwei Parameter – einer (wie die anonymen Funktionen, die an „map/filter/forEach“ übergeben werden) ist der zu bearbeitende Iterator.Es gibt jedoch noch ein weiteres Argument dafür, dass die zur Reduzierung übergebene anonyme Funktion von diesen Funktionen nicht akzeptiert wird, und zwar der Wert, der zwischen Funktionsaufrufen weitergegeben wird, oft auch als bezeichnet Memo.

Beachten Sie, dass Array.filter() zwar nur ein Argument (eine Funktion) akzeptiert, Array.reduce() jedoch auch ein wichtiges (wenn auch optionales) zweites Argument akzeptiert:ein Anfangswert für „memo“, der als erstes Argument an diese anonyme Funktion übergeben wird und anschließend mutiert und zwischen Funktionsaufrufen weitergegeben werden kann.(Wenn es nicht angegeben wird, ist „memo“ im ersten anonymen Funktionsaufruf standardmäßig der erste Iteratee, und das Argument „iteratee“ ist tatsächlich der zweite Wert im Array.)

In unserem Fall übergeben wir zu Beginn ein leeres Array und entscheiden dann basierend auf unserer Funktion, ob wir unseren Iteratee in unser Array einfügen möchten oder nicht – das ist der Filterprozess.

Schließlich geben wir bei jedem anonymen Funktionsaufruf unser „in Bearbeitung befindliches Array“ zurück, und Reduce nimmt diesen Rückgabewert und übergibt ihn als Argument (Memo genannt) an den nächsten Funktionsaufruf.

Dadurch können Filter und Zuordnung in einer Iteration erfolgen, wodurch sich die Anzahl der erforderlichen Iterationen halbiert.:) :)

Eine ausführlichere Erklärung finden Sie unter MDN oder den Link oben.:) :)

Einfaches Beispiel für einen Reduce-Aufruf:

let array = [1,2,3];
const initialMemo = [];

array = array.reduce((memo, iteratee) => {
    // if condition is our filter
    if (iteratee > 1) {
        // what happens inside the filter is the map
        memo.push(iteratee * 2); 
    }

    // this return value will be passed in as the 'memo' argument
    // to the next call of this function, and this function will have
    // every element passed into it at some point.
    return memo; 
}, initialMemo)

console.log(array) // [4,6], equivalent to [(2 * 2), (3 * 2)]

prägnantere Version:

[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])

Beachten Sie, dass der erste Iterationswert nicht größer als eins war und daher gefiltert wurde.Beachten Sie auch das initialMemo, das nur so benannt wurde, um seine Existenz klarzustellen und die Aufmerksamkeit darauf zu lenken.Erneut wird es als „Memo“ an den ersten anonymen Funktionsaufruf übergeben, und dann wird der zurückgegebene Wert der anonymen Funktion als „Memo“-Argument an die nächste Funktion übergeben.

Ein weiteres Beispiel für den klassischen Anwendungsfall für Memo wäre die Rückgabe der kleinsten oder größten Zahl in einem Array.Beispiel:

[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
// ^this would return the largest number in the list.

Ein Beispiel dafür, wie man eine eigene Reduktionsfunktion schreibt (das hilft meiner Meinung nach oft beim Verständnis solcher Funktionen):

test_arr = [];

// we accept an anonymous function, and an optional 'initial memo' value.
test_arr.my_reducer = function(reduceFunc, initialMemo) {
    // if we did not pass in a second argument, then our first memo value 
    // will be whatever is in index zero. (Otherwise, it will 
    // be that second argument.)
    const initialMemoIsIndexZero = arguments.length < 2;

    // here we use that logic to set the memo value accordingly.
    let memo = initialMemoIsIndexZero ? this[0] : initialMemo;

    // here we use that same boolean to decide whether the first
    // value we pass in as iteratee is either the first or second
    // element
    const initialIteratee = initialMemoIsIndexZero ? 1 : 0;

    for (var i = initialIteratee; i < this.length; i++) {
        // memo is either the argument passed in above, or the 
        // first item in the list. initialIteratee is either the
        // first item in the list, or the second item in the list.
        memo = reduceFunc(memo, this[i]);
    }

    // after we've compressed the array into a single value,
    // we return it.
    return memo;
}

Die eigentliche Implementierung ermöglicht zum Beispiel den Zugriff auf Dinge wie den Index, aber ich hoffe, dass Sie dadurch ein unkompliziertes Gefühl für das Wesentliche bekommen.

Das ist nicht das, was Map tut.Du willst wirklich Array.filter.Oder wenn Sie die Elemente wirklich aus der ursprünglichen Liste entfernen möchten, müssen Sie dies unbedingt mit einer for-Schleife tun.

Sie müssen jedoch beachten, dass die Array.filter wird nicht in allen Browsern unterstützt, daher müssen Sie einen Prototyp erstellen:

//This prototype is provided by the Mozilla foundation and
//is distributed under the MIT license.
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license

if (!Array.prototype.filter)
{
    Array.prototype.filter = function(fun /*, thisp*/)
    {
        var len = this.length;

        if (typeof fun != "function")
            throw new TypeError();

        var res = new Array();
        var thisp = arguments[1];

        for (var i = 0; i < len; i++)
        {
            if (i in this)
            {
                var val = this[i]; // in case fun mutates this

                if (fun.call(thisp, val, i, this))
                   res.push(val);
            }
        }

        return res;
    };
}

Und auf diese Weise können Sie Prototypen für jede Methode erstellen, die Sie benötigen.

Ich platziere diese Antwort hier, weil die auf dieser Seite geteilten Polyfills miserabel sind

function reduce(f, y, xs, context) {
  var acc = y;
  for (var i = 0, len = xs.length; i < len; i++)
    acc = f.call(context, acc, xs[i], i, xs);
  return acc;
}

function reduce1(f, xs, context) {
  if (xs.length === 0)
    throw Error('cannot reduce empty array without initial value');
  else
    return reduce(f, xs[0], xs.slice(1), context);
}

function map(f, xs, context) {
  return reduce(function(acc, x, i) {
    return acc.concat([
      f.call(context, x, i, xs)
    ]);
  }, [], xs);
}

function filter(f, xs, context) {
  return reduce(function(acc, x, i) {
    if (f.call(context, x, i, xs))
      return acc.concat([x]);
    else
      return acc;
  }, [], xs);
}

Prototypen erweitern

if (Array.prototype.reduce === undefined) {
  Array.prototype.reduce = function(f, initialValue, context) {
    if (initialValue === undefined)
      return reduce1(f, this, context);
    else
      return reduce(f, initialValue, this, context);
  };
}

if (Array.prototype.map === undefined) {
  Array.prototype.map = function(f, context) {
    return map(f, this, context);
  };
}

if (Array.prototype.filter === undefined) {
  Array.prototype.filter = function(f, context) {
    return filter(f, this, context);
  };
}
var arr = [1,2,'xxx','yyy']

arr = arr.filter(function(e){ return e != 'xxx' });

arr  // [1, 2, "yyy"]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top