duplicados - Eliminar elementos con Array.map en JavaScript
map filter javascript (6)
Me gustaría filtrar una matriz de elementos utilizando la función map()
. 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, me olvidé de filter()
, lo que quería es en realidad un filter()
luego un map()
.
EDIT2: Gracias por señalar que 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.
Coloco esta respuesta aquí porque los polifills 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);
}
extender 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);
};
}
Debe usar el método de filter
lugar del mapa, a menos que desee mutar los elementos en la matriz, además del filtrado.
p.ej.
var filteredItems = items.filter(function(item)
{
return ...some condition...;
});
[Editar: Por supuesto, siempre sourceArray.filter(...).map(...)
hacer sourceArray.filter(...).map(...)
para filtrar y mutar]
En realidad, la respuesta aceptada te está fallando. ¿De verdad quieres usar reducir, a la:
http://elijahmanor.com/reducing-filter-and-map-down-to-reduce/
Pero, así que no solo pongo un enlace, aquí está la versión corta.
Le das reducir 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 iteratee para ser operado. Hay otro argumento para la función anónima pasada para reducir, sin embargo, que esas funciones no aceptan, y ese es el valor que se transmitirá entre las llamadas a funciones, a menudo referido como la nota .
Tenga en cuenta que aunque 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 su primer argumento, y posteriormente puede ser mutado y transmitido entre llamadas a funciones. (Si no se proporciona, entonces ''memo'' en la primera llamada de función anónima será por defecto el primer iteratee, y el argumento ''iteratee'' será en realidad el segundo valor en el array)
En nuestro caso, vamos a pasar una matriz vacía para comenzar, y luego elegir si inyectar nuestra iteración en nuestra matriz o no en función de nuestra función: este es el proceso de filtrado.
Finalmente, devolveremos nuestra ''matriz en progreso'' en cada llamada de función anónima, y reduceremos ese valor de retorno y lo pasaremos como un argumento (llamado memo) a su próxima llamada de función.
Esto permite que el filtro y el mapa sucedan en una iteración, reduciendo a la mitad nuestro número de iteraciones requeridas. :)
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 sucinta
[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
Tenga en cuenta que la primera iteración no fue mayor que uno, por lo que se filtró. También tenga en cuenta la nota inicial, nombrada solo para aclarar su existencia y llamar la atención sobre ella. Una vez más, se pasa como ''memo'' a la primera llamada de función anónima, y luego el valor devuelto de la función anónima se pasa como el argumento ''memo'' a la siguiente función.
Otro ejemplo del caso de uso clásico para memo sería devolver el número más pequeño o más grande en 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 entender funciones como estas, me parece):
test_arr = [];
// we accept an anonymous function, and an optional ''initial memo'' value.
test_arr.my_reducer = function(reduceFunc, initialMemo) {
// if we passed in two arguments, then our first memo value
// will be whatever is in index zero. (Otherwise, it will
// be that second argument.)
const initialMemoIsIndexZero = arguments.length > 1;
// here we use that logic to set the memo value accordingly.
let memo = initialMemoIsIndexZero ? initialMemo : this[0];
// 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;
}
No probé a fondo esa implementación, y simplemente la escribí fuera de mi cabeza, pero en mis dos casos de prueba básicos parecía funcionar. La implementación real permite el acceso a cosas como el índice, por ejemplo, pero espero que esto lo ayude a obtener una idea sencilla de lo esencial.
Eso no es lo que hace el mapa. Realmente quieres Array.filter . O si realmente desea eliminar los elementos de la lista original, tendrá que hacerlo imperativamente con un ciclo for.
Sin embargo, debe tener en cuenta que Array.filter
no es compatible con todos los navegadores, por lo que debe Array.filter
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 prototipar cualquier método que pueda necesitar.
var arr = [1,2,''xxx'',''yyy'']
arr = arr.filter(function(e){ return e != ''xxx'' });
arr // [1, 2, "yyy"]