繁体   English   中英

如何在使用 Javascript.reduce 而不是.filter().map() 构建新的对象数组时添加属性?

[英]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'}
]

我们想要

  1. 作为该组水果的子集或过滤器的新数组。 (例如,我们可以说我们想要“新鲜水果”......假设我们有一个 function, isFresh ,它决定了这个条件)

  2. 我们希望这个新数组中的每个水果都添加一个新属性(或键值对),由 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;
    }, []);

所以这仍然是一个有答案的问题,让我问这个

  1. 为什么这种扩展语法是必要的? 为什么我第一次尝试使用 .reduce() 方法没有成功? 事后看来,我现在可以看到为什么它不应该起作用,但我认为我坚持认为 reduce 创建一个临时状态/变量而不是实时编辑现有变量。

  2. 使用.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM