![](/img/trans.png)
[英]Using map with reduce in javascript to filter objects in an array
[英]How to add a property when building a new array of objects using Javascript .reduce, as opposed to .filter().map()?
我有使用.filter().map()成功运行的代码,但我想使用 .reduce( )重写它,以便只使用一次迭代,而不是前一种情况下的两次。
假设我们有一个水果对象数组......
var fruitArray = [
{name: 'Apple', color: 'red'},
{name: 'Banana', color: 'yellow'},
{name: 'Kiwi', color: 'green'},
{name: 'Blueberry', color: 'blue'},
{name: 'Orange', color: 'orange'}
]
我们想要
作为该组水果的子集或过滤器的新数组。 (例如,我们可以说我们想要“新鲜水果”......假设我们有一个 function, isFresh ,它决定了这个条件)
我们希望这个新数组中的每个水果都添加一个新属性(或键值对),由 foo: 'bar' 表示。
我能够使用.filter()和.map()以相当简单的方式做到这一点:
var freshFruit = fruitArray.filter(fruit => isFresh(fruit)).map((fruit) => {
const value = 'bar'
return {...fruit, foo: value }
});
console.log(freshFruit);
/*
[
{ name: 'Apple', color: 'red', foo: 'bar' },
{ name: 'Kiwi', color: 'green', foo: 'bar' },
{ name: 'Blueberry', color: 'blue', foo: 'bar' }
]
*/
当我尝试使用 reduce 来做到这一点时
var freshFruit = fruitArray.reduce((previousValue, fruit)=>{
if (isFresh(fruit)) {
const value = 'bar'
fruit.foo = value
previousValue.push(fruit);
}
return previousValue;
}, []);
我得到了freshFruit所需的output,但后来我注意到它也编辑了我原来的fruitArray
console.log(fruitArray);
/*
[
{ name: 'Apple', color: 'red', foo: 'bar' },
{ name: 'Banana', color: 'yellow' },
{ name: 'Kiwi', color: 'green', foo: 'bar' },
{ name: 'Blueberry', color: 'blue', foo: 'bar' },
{ name: 'Orange', color: 'orange' }
]
*/
注意 reduce 是如何添加 foo 属性的。
...
通过输入这个过程,我可能已经解决了我自己的问题。
我想我需要在减少 function 中使用扩展运算符
var freshFruit = fruitArray.reduce((previousValue, fruit)=>{
if (isFresh(fruit)) {
const value = 'bar'
previousValue.push({...fruit, foo: value});
}
return previousValue;
}, []);
所以这仍然是一个有答案的问题,让我问这个
为什么这种扩展语法是必要的? 为什么我第一次尝试使用 .reduce() 方法没有成功? 事后看来,我现在可以看到为什么它不应该起作用,但我认为我坚持认为 reduce 创建一个临时状态/变量而不是实时编辑现有变量。
使用.reduce() 而不是.filter().map() 是否有材料性能优势? 对于任何想使用 a.filter().map() 的人来说,这应该是一个一般性的建议吗?
使用 .reduce(
.reduce()
而不是.filter().map()
是否有材料性能优势? 这应该是对任何想使用.filter().map()
的人的一般建议吗?
我不会太担心迭代两次的开销,因为迭代是一个非常简单的过程。 但是,如果 arrays 很大,使用.filter().map()
意味着需要创建一个额外的临时数组来保存.filter()
的结果,然后才能开始映射。 这可能是大量的 memory,并且必须将 go 回到开头,因为.map()
的缓存局部性很差。
但是,在我看来, reduce()
通常比filter()
和map()
更难编写和理解。 因此,除非性能至关重要,否则我更喜欢使用.filter().map()
。
为什么我第一次尝试使用 .reduce() 方法没有成功?
我只是重复了你的代码,它工作正常,检查这个例子。
您记录原始的fruitArray
数组而不是处理后的freshFruit
数组
const fruitArray = [ {name: 'Apple', color: 'red'}, {name: 'Banana', color: 'yellow'}, {name: 'Kiwi', color: 'green'}, {name: 'Blueberry', color: 'blue'}, {name: 'Orange', color: 'orange'}, ]; const isFresh = ({ name }) => ['Apple', 'Kiwi', 'Blueberry'].includes(name); const result = fruitArray.reduce((previousValue, fruit)=>{ if (isFresh(fruit)) { const value = 'bar' fruit.foo = value previousValue.push(fruit); } return previousValue; }, []); console.log(result);
.as-console-wrapper { max-height: 100%;important: top: 0 }
作为旁注,另一种使用.flatMap
进行映射和过滤的“hacky-one-liner”方式:
const fruitArray = [ {name: 'Apple', color: 'red'}, {name: 'Banana', color: 'yellow'}, {name: 'Kiwi', color: 'green'}, {name: 'Blueberry', color: 'blue'}, {name: 'Orange', color: 'orange'}, ]; const isFresh = ({ name }) => ['Apple', 'Kiwi', 'Blueberry'].includes(name); const result = fruitArray.flatMap((fruit) => isFresh(fruit)? {...fruit, foo: 'bar' }: []); console.log(result);
.as-console-wrapper { max-height: 100%;important: top: 0 }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.