【问题标题】:Why doesn't the accumulator in my reduce function take on the callback's return value?为什么我的 reduce 函数中的累加器不接受回调的返回值?
【发布时间】:2018-06-12 17:04:25
【问题描述】:

我有一个对象数组,我想对整个数组的对象中的所有“bps”值求和。

我的对象数组如下所示:

arr = [
    {
        date: "2017-06-14T14:00:00.000Z",
        bps: 2
    },
    ...
]

这是我的 reduce 函数:

arr.reduce((accum, currVal) => {
        console.log(accum.bps);
        console.log(currVal.bps);
        console.log(accum.bps + currVal.bps);
        return accum.bps + currVal.bps;
    }, {
        bps: 0
    });

根据输出到控制台的内容,reduce 函数的第一次迭代后,返回值 0 并没有成为下一次迭代的累加器(它变成“未定义”)。为什么会出现这种情况?我的函数应该如何总结我数组中的所有“bps”值?

这就是控制台显示的内容

scripts.js:1024 0
scripts.js:1025 0
scripts.js:1026 0
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 1.95
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1024 undefined
scripts.js:1025 0
scripts.js:1026 NaN
scripts.js:1031 NaN

【问题讨论】:

  • return accum.bps + currVal.bps 返回一个数字 ... 它没有名为 bps 的属性
  • 试试arr.map(({bps}) => bps).reduce((a, b) => a + b);
  • 我现在看到了。感谢您的澄清 - 现在工作正常。
  • 也可以使用 lodash _.sumBy(arr, elem => elem.bps)
  • 感谢 fredrik.hjamer。实际上我今天开始使用 lodash,所以我会考虑摆脱我自己编写的函数 :)

标签: javascript arrays object functional-programming


【解决方案1】:

您应该返回一个具有bps 键的对象,而不是纯和。

return { bps: accum.bps + currVal.bps }; 而不是 return accum.bps + currVal.bps;


arr
  .reduce((accum, currVal) => {
    console.log(accum.bps);
    console.log(currVal.bps);
    console.log(accum.bps + currVal.bps);
    return { bps: accum.bps + currVal.bps };
  }, {
    bps: 0
  })
  .bps;

或者(这实际上会更快,尤其是对于长数组,因为它不会创建不必要的对象,只会创建结果对象)。

const bpsResult = {
  bps:
    arr
      .reduce((accum, currVal) => {
        console.log(accum);
        console.log(currVal);
        console.log(accum + currVal);
        return accum + currVal;
    },
    0);
  };

【讨论】:

  • 不确定第二段代码! currVal 将是一个对象,不是吗?
  • 替代解决方案仅在 arr 的内容不同时才有效,或者您对 map 进行预处理以提取 bps 值。
  • 哦,不!你们是对的! @ShadowRanger 我没有注意到数组中对象的第二个字段!
【解决方案2】:

由于您的 reduce 只是将所有 .bps 值相加,您可以简单地将所有数组项映射到一个数字数组,然后将它们相加

arr.map(({bps}) => bps)
.reduce((a, b) => a + b);

甚至

arr.reduce((accum, {bps}) => accum + bps, 0);

【讨论】:

  • 这个答案比我的好!
【解决方案3】:

这行得通。 accum 是一个数字,所以不要使用 accum.bps。另外,初始值是一个数字,所以不要使用{bps: 0},直接使用0即可。

arr = [{
    date: "2017-06-14T14:00:00.000Z",
    bps: 2
}, {
    date: "2017-05-14T14:00:00.000Z",
    bps: 9
}, {
    date: "2017-08-14T14:00:00.000Z",
    bps: 4
}]

// Here is my reduce function:

arr.reduce((accum, currVal) => {
    console.log("accum-" + accum);
    console.log("currVal.bps-" + currVal.bps);
    console.log("return value-" + (accum + currVal.bps));
    return accum + currVal.bps;
}, 0);

这是输出:

accum-0
currVal.bps-2
return value-2
accum-2
currVal.bps-9
return value-11
accum-11
currVal.bps-4
return value-15

【讨论】:

    猜你喜欢
    • 2017-06-12
    • 2018-11-21
    • 2021-06-28
    • 2018-03-05
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    相关资源
    最近更新 更多