Domanda

Vorrei filtrare una serie di elementi utilizzando il file map() funzione.Ecco uno snippet di codice:

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

Il problema è che gli elementi filtrati utilizzano ancora spazio nell'array e vorrei cancellarli completamente.

Qualche idea?

MODIFICARE:Grazie, me ne ero dimenticato filter(), quello che volevo è in realtà a filter() poi un map().

EDIT2:Grazie per averlo indicato map() E filter() non sono implementati in tutti i browser, anche se il mio codice specifico non era destinato a essere eseguito in un browser.

È stato utile?

Soluzione

Dovresti usare il filter metodo anziché map a meno che non si desideri modificare gli elementi nell'array, oltre al filtraggio.

per esempio.

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

[Modificare:Certo che potresti sempre farlo sourceArray.filter(...).map(...) sia per filtrare che per mutare]

Altri suggerimenti

Ho scritto una risposta qualche tempo fa e le mie opinioni sono cambiate.Consiglio di dare un'occhiata al mio post sul blog che amplia questo argomento e lo spiega molto meglio.Fornisce anche un confronto JSperf alla fine delle alternative.

Il tl;dr è questo:Per realizzare ciò che stai chiedendo (filtraggio e mappatura all'interno di una chiamata di funzione), dovresti usare Array.reduce().comunque, il più leggibile E solitamente più veloce2 l'approccio consiste nell'utilizzare semplicemente il filtro e la mappa concatenati insieme:

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

Quella che segue è una descrizione di come Array.reduce() funziona e come può essere utilizzato per realizzare filtri e mappe in un'unica iterazione.Se questo è troppo sintetico, consiglio vivamente di vedere il post del blog collegato sopra, che è un'introduzione molto più amichevole con esempi e progressioni chiari.

Dai a reduce un argomento che è una funzione (solitamente anonima).

Quella funzione anonima accetta due parametri: uno (come le funzioni anonime passate a map/filter/forEach) è l'iterato su cui operare.C'è un altro argomento a favore della riduzione della funzione anonima passata, tuttavia, che tali funzioni non accettano, e cioè il valore che verrà passato tra le chiamate di funzione, spesso indicato come promemoria.

Tieni presente che mentre Array.filter() accetta solo un argomento (una funzione), Array.reduce() accetta anche un secondo argomento importante (anche se facoltativo):un valore iniziale per "memo" che verrà passato a quella funzione anonima come primo argomento e successivamente potrà essere modificato e passato tra le chiamate di funzione.(Se non viene fornito, allora 'memo' nella prima chiamata di funzione anonima sarà per impostazione predefinita il primo iterato e l'argomento 'iterate' sarà effettivamente il secondo valore nell'array)

Nel nostro caso, passeremo un array vuoto per iniziare, quindi sceglieremo se inserire o meno il nostro iterato nell'array in base alla nostra funzione: questo è il processo di filtraggio.

Infine, restituiremo il nostro 'array in progress' ad ogni chiamata di funzione anonima e reduce prenderà quel valore restituito e lo passerà come argomento (chiamato memo) alla successiva chiamata di funzione.

Ciò consente al filtro e alla mappa di verificarsi in un'unica iterazione, dimezzando il numero di iterazioni richieste.:)

Per una spiegazione più completa fare riferimento a MDN o il collegamento qui sopra.:)

Esempio base di chiamata Reduce:

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

versione più concisa:

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

Si noti che il primo iterato non era maggiore di uno e quindi è stato filtrato.Da notare anche l'inizialeMemo, nominata proprio per chiarirne l'esistenza e richiamare l'attenzione su di essa.Ancora una volta, viene passato come "memo" alla prima chiamata di funzione anonima, quindi il valore restituito dalla funzione anonima viene passato come argomento "memo" alla funzione successiva.

Un altro esempio del classico caso d'uso di memo sarebbe la restituzione del numero più piccolo o più grande in un array.Esempio:

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

Un esempio di come scrivere la propria funzione di riduzione (questo spesso aiuta a comprendere funzioni come queste, trovo):

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

L'implementazione reale consente l'accesso a cose come l'indice, ad esempio, ma spero che questo ti aiuti a fartene un'idea semplice.

Non è quello che fa la mappa.Vuoi veramente Filtro.array.Oppure, se vuoi davvero rimuovere gli elementi dall'elenco originale, dovrai farlo imperativamente con un ciclo for.

È necessario notare tuttavia che il Array.filter non è supportato in tutti i browser quindi è necessario prototipare:

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

E così facendo, puoi prototipare qualsiasi metodo di cui potresti aver bisogno.

Sto inserendo questa risposta qui perché i polyfill condivisi in questa pagina sono spaventosi

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

estendere i prototipi

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"]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top