Pregunta

Me gustaría filtrar una variedad de elementos usando el map() función.Aquí hay un fragmento de código:

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

El problema es que los elementos filtrados todavía usan espacio en la matriz y me gustaría eliminarlos por completo.

¿Alguna idea?

EDITAR:Gracias, lo olvidé filter(), lo que quería es en realidad un filter() Entonces un map().

EDITAR2:Gracias por señalar eso map() y filter() no están implementados en todos los navegadores, aunque mi código específico no estaba destinado a ejecutarse en un navegador.

¿Fue útil?

Solución

Deberías usar el filter método en lugar de map a menos que desee mutar los elementos de la matriz, además de filtrar.

p.ej.

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

[Editar:Por supuesto que siempre puedes hacer sourceArray.filter(...).map(...) para filtrar y mutar]

Otros consejos

Escribí una respuesta hace un tiempo y mis opiniones cambiaron.Recomiendo revisar mi entrada en el blog lo que amplía este tema y lo explica mucho mejor.También ofrece una comparación de JSperf al final de las alternativas.

El tl;dr es este:Para lograr lo que está pidiendo (filtrado y mapeo dentro de una llamada de función), debe usar Array.reduce().sin embargo, el más legible y generalmente más rápido2 El enfoque es simplemente usar filtro y mapa encadenados:

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

Lo que sigue es una descripción de cómo Array.reduce() funciona y cómo se puede utilizar para realizar filtros y mapas en una sola iteración.Si esto está demasiado condensado, recomiendo ver la publicación del blog vinculada arriba, que es una introducción mucho más amigable con ejemplos claros y progresión.

Le das a reduce un argumento que es una función (generalmente anónima).

Esa función anónima toma dos parámetros: uno (como las funciones anónimas pasadas a map/filter/forEach) es el iterado sobre el que se va a operar.Sin embargo, hay otro argumento para la función anónima pasada para reducir que esas funciones no aceptan, y es el valor que se pasará entre llamadas a funciones, a menudo denominado memorándum.

Tenga en cuenta que mientras Array.filter() toma solo un argumento (una función), Array.reduce() también toma un segundo argumento importante (aunque opcional):un valor inicial para 'memo' que se pasará a esa función anónima como primer argumento y, posteriormente, se puede mutar y pasar entre llamadas a funciones.(Si no se proporciona, entonces 'memo' en la primera llamada a función anónima será de forma predeterminada el primer iterado, y el argumento 'iteratee' en realidad será el segundo valor en la matriz)

En nuestro caso, pasaremos una matriz vacía para comenzar y luego elegiremos si inyectamos nuestro iterado en nuestra matriz o no según nuestra función; este es el proceso de filtrado.

Finalmente, devolveremos nuestra 'matriz en progreso' en cada llamada a función anónima, y ​​reducir tomará ese valor de retorno y lo pasará como argumento (llamado memo) a su siguiente llamada a función.

Esto permite que el filtro y el mapa se realicen en una sola iteración, lo que reduce a la mitad el número de iteraciones necesarias.:)

Para una explicación más completa, consulte MDN o el enlace de arriba.:)

Ejemplo básico de una llamada Reducir:

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

versión más resumida:

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

Observe que el primer iterado no fue mayor que uno, por lo que se filtró.Tenga en cuenta también el Memo inicial, nombrado sólo para dejar clara su existencia y llamar la atención sobre él.Una vez más, se pasa como 'memo' a la primera llamada a función anónima, y ​​luego el valor devuelto de la función anónima se pasa como argumento 'memo' a la siguiente función.

Otro ejemplo del caso de uso clásico de memo sería devolver el número más pequeño o más grande de una matriz.Ejemplo:

[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 ejemplo de cómo escribir su propia función de reducción (esto a menudo ayuda a comprender funciones como estas, según creo):

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

La implementación real permite el acceso a cosas como el índice, por ejemplo, pero espero que esto le ayude a tener una idea sencilla de su esencia.

Eso no es lo que hace el mapa.De verdad quieres filtro.matriz.O si realmente desea eliminar los elementos de la lista original, necesitará hacerlo imperativamente con un bucle for.

Debes tener en cuenta sin embargo que el Array.filter no es compatible con todos los navegadores, por lo que debe crear un prototipo:

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

Y al hacerlo, puede crear prototipos de cualquier método que necesite.

Estoy colocando esta respuesta aquí porque los polyfills compartidos en esta página son abismales.

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

ampliar prototipos

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"]
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top