在JavaScript中使用Array.map删除元素
我想使用在JavaScript中使用Array.map删除元素,javascript,functional-programming,data-manipulation,client-side,Javascript,Functional Programming,Data Manipulation,Client Side,我想使用map()函数过滤项目数组。以下是一段代码片段: var filteredItems = items.map(function(item) { if( ...some condition... ) { return item; } }); 问题是,过滤掉的项目仍然会占用数组中的空间,我想完全清除它们 有什么想法吗 编辑:谢谢,我忘记了filter(),我想要的实际上是一个filter()然后是一个map() EDIT2:感谢您指出并非所有浏览器都
map()
函数过滤项目数组。以下是一段代码片段:
var filteredItems = items.map(function(item)
{
if( ...some condition... )
{
return item;
}
});
问题是,过滤掉的项目仍然会占用数组中的空间,我想完全清除它们
有什么想法吗
编辑:谢谢,我忘记了filter()
,我想要的实际上是一个filter()
然后是一个map()
EDIT2:感谢您指出并非所有浏览器都实现了
map()
和filter()。你真的想要。或者,如果您确实想从原始列表中删除元素,则需要使用for循环强制执行此操作。您应该使用filter
方法,而不是map方法,除非您想在过滤之外对数组中的项进行变异
例如
[编辑:当然,您可以始终执行sourceArray.filter(…).map(…)
以同时进行筛选和变异]您必须注意的是,并非所有浏览器都支持数组.filter
,因此,您必须原型化:
//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;
};
}
<代码> //这个原型是由Mozilla基金会提供的。
//是根据麻省理工学院许可证发行的。
//http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
if(!Array.prototype.filter)
{
Array.prototype.filter=函数(fun/*,thisp*/)
{
var len=此长度;
如果(乐趣的类型!=“功能”)
抛出新的TypeError();
var res=新数组();
var thisp=参数[1];
对于(变量i=0;i
这样,您就可以创建您可能需要的任何方法的原型 排列
var-arr=[1,2,3]
//ES5语法
arr=arr.filter(函数(项){返回项!=3})
//ES2015语法
arr=arr.filter(项=>项!=3)
console.log(arr)
受写这个答案的启发,我后来扩展并写了一篇博客文章,详细讨论了这个问题。如果您想更深入地理解如何思考这个问题,我建议您——我试着一点一点地解释它,并在最后给出一个JSperf比较,讨论速度方面的考虑
也就是说,**tl;dr是这样的:
要实现您的要求(在一个函数调用中进行过滤和映射),可以使用Array.reduce()
**。
然而,更具可读性的和(不太重要)通常更快的方法是只使用链接在一起的过滤器和映射:
[1,2,3]。过滤器(num=>num>2)。映射(num=>num*2)
下面介绍了Array.reduce()
的工作原理,以及如何使用它在一次迭代中完成过滤和映射。再一次,如果这篇文章过于浓缩,我强烈建议你看看上面的链接,这是一篇更加友好的介绍,有着清晰的例子和进展
您给出的reduce参数是一个(通常是匿名)函数
var arraytoclean = [{v:65, toberemoved:"gronf"}, {v:12, toberemoved:null}, {v:4}];
arraytoclean.map((x,i)=>x.toberemoved=undefined);
console.dir(arraytoclean);
这个匿名函数有两个参数——一个(就像传递给map/filter/forEach的匿名函数一样)是要操作的迭代器对象。但是,传递匿名函数的另一个参数是,这些函数不接受,即在函数调用之间传递的值,通常称为memo
请注意,虽然Array.filter()只接受一个参数(一个函数),Array.reduce()还接受一个重要的(尽管是可选的)第二个参数:“memo”的初始值将作为其第一个参数传递到匿名函数中,随后可以在函数调用之间进行变异和传递。(如果未提供,则默认情况下,第一个匿名函数调用中的'memo'将是第一个iteratee,而'iteratee'参数实际上将是数组中的第二个值)
在我们的例子中,我们将传入一个空数组开始,然后根据函数选择是否将迭代者注入到数组中——这是过滤过程
最后,我们将在每次匿名函数调用时返回“array in progress”,reduce将获取该返回值并将其作为参数(称为memo)传递给下一次函数调用
这允许过滤器和映射在一次迭代中发生,将我们所需的迭代次数减少了一半——不过每次迭代只需做两倍的工作,因此除了函数调用之外,没有什么真正节省了,函数调用在javascript中并不昂贵
有关更完整的解释,请参阅文档(或本答案开头引用的我的帖子)
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)]
更简洁的版本:
[1,2,3].reduce((memo, value) => value > 1 ? memo.concat(value * 2) : memo, [])
注意,第一个iteratee不大于1,因此被过滤。还要注意名字的首字母memo,它的名字只是为了清楚地表明它的存在并引起人们的注意。再次,它作为'memo'传递给第一个匿名函数调用,然后匿名函数的返回值作为'memo'参数传递给下一个函数
var arraytoclean = [{v:65, toberemoved:"gronf"}, {v:12, toberemoved:null}, {v:4}];
arraytoclean.map((x,i)=>x.toberemoved=undefined);
console.dir(arraytoclean);
memo的另一个经典用例示例是返回数组中的最小或最大数字。例如:
[7,4,1,99,57,2,1,100].reduce((memo, val) => memo > val ? memo : val)
// ^this would return the largest number in the list.
关于如何编写自己的reduce函数的示例(我发现,这通常有助于理解此类函数):
test_arr=[];
//我们接受匿名函数和可选的“初始备注”值。
test\u arr.my\u reducer=函数(reduceFunc,initialMemo){
//如果我们没有传入第二个参数,那么我们的第一个memo值
//将是索引0中的任何内容。(否则,它将
//这是第二个论点。)
常量initialMemorisIndexZero=arguments.leng
var arraytoclean = [{v:65, toberemoved:"gronf"}, {v:12, toberemoved:null}, {v:4}];
arraytoclean.map((x,i)=>x.toberemoved=undefined);
console.dir(arraytoclean);
state.map(item => {
if(item.id === action.item.id){
return {
id : action.item.id,
name : item.name,
price: item.price,
quantity : item.quantity-1
}
}else{
return item;
}
}).filter(item => {
if(item.quantity <= 0){
return false;
}else{
return true;
}
});
let array = [1, 2, 3, 4, 5, 6, 7, 8];
let mapped = array
.filter(x => {
let computation = x / 2 + 1;
let isIncluded = computation % 2 === 0;
return isIncluded;
})
.map(x => {
let computation = x / 2 + 1;
return `${x} is included because ${computation} is even`
})
// Output: [2 is included because 2 is even, 6 is included because 4 is even]
let array = [1, 2, 3, 4, 5, 6, 7, 8];
let mapped = array
.map(x => {
let computation = x / 2 + 1;
let isIncluded = computation % 2 === 0;
if (isIncluded) {
return `${x} is included because ${computation} is even`
} else {
return undefined
}
})
.filter(x => typeof x !== "undefined")