【问题标题】:discrepancy in array.reduce javascriptarray.reduce javascript 中的差异
【发布时间】:2018-01-30 14:09:11
【问题描述】:

我花了几个小时尝试调试特定代码,最后我注意到我不理解 arr reduce 函数的一些东西。以下面的代码示例为例

var arr = [{
  start: 1,
  value: 4
}, {
  start: 2,
  value: 5
}, {
  start: 3,
  value: 1
}, {
  start: 4,
  value: 41
}, {
  start: 5,
  value: 14
}, {
  start: 6,
  value: 3
}];

const getMinValue = function(a, b) {
  return (a.value < b.value) ? a.start : b.start;
}

console.log('The min value ', arr.reduce(getMinValue));

上面的控制台返回 6。然而,从数组中,它的值在start:3 处是最小值。然而,将代码重写为下面,

var arr = [{
  start: 1,
  value: 4
}, {
  start: 2,
  value: 5
}, {
  start: 3,
  value: 1
}, {
  start: 4,
  value: 41
}, {
  start: 5,
  value: 14
}, {
  start: 6,
  value: 3
}];

const getMinValue = function(a, b) {
  return (a.value < b.value) ? a : b;
}

console.log('The min value ', arr.reduce(getMinValue));

返回完全正确的对象{start: 3, value: 1}。因此

console.log('The min value ', arr.reduce(getMinValue).start);

是正确的。为什么第一个不同?为什么它返回 6 ? .我对 reduce 或我的 getMin 函数有什么误解吗?任何帮助将不胜感激。

【问题讨论】:

  • 在下一次迭代中,您将在 reduce 中返回一个数字为 a。数字没有valuestart 属性。
  • 你的 reduce 函数变成了 return (undefined &lt; undefined ? undefined : b.start,所以你总是返回 b.start 并最终返回数组中最终对象的起始值。
  • @Paulpro 哦哦哦 oic 。我的比较取决于返回的先前值? OMG,完全忽略了这一点。谢谢。

标签: javascript arrays reduce


【解决方案1】:

为什么返回 6?

因为a 是一个accumulator,它也恰好是每次迭代的返回值

这一行

return (a.value < b.value) ? a.start : b.start;

翻译成条件表达式为

{start: 1, value : 4}.value < { start: 2, value: 5}.value

下次再来

(4).value < { start: 3,  value: 1 } //false hence return 1

因为(4).valueundefined 并且与undefined 比较总是返回false

最后一次迭代将是

(14).value < { start: 6,  value: 3 } 

返回6

【讨论】:

  • @sabithpocker 你是对的...未定义的比较总是返回 false
【解决方案2】:

因为从传递给 reduce 的函数返回的任何内容都将成为 a 的 NEXT 值。

const someReducer = (accumulator, x) => {
  // whatever I return here is the new value of the accumulator
  return accumulator.value < x.value ? accumulator.start : x.start;
}

someArray.reduce(someReducer);

accumulator 第一次的值是一个对象,就像value。 然后你返回一个数字。 第二次时,accumulator 现在是您返回的号码。

一般情况下,您还应该使用reduce 的第二个参数,它是reducer 的初始值。如果您的理想 accumulator 类型与数组中的值类型不同,这一点非常重要。

如果您有一个稍微简单的版本,您可以考虑:

values.reduce(getMinValue, Infinity);

你的初始函数可以正常工作,如果它被更改为

const getMinValue = (accumulator, x) =>
  accumulator < x.value ? accumulator : x.value;

在此示例中,累加器始终是一个数字,而 x 是您的对象之一。这不是您在原始问题中所要求的,但是

.reduce(getMinValue, { start: 0, value: Infinity })

也可以。

【讨论】:

    【解决方案3】:

    filter() 方法返回一个新数组,该数组由通过对原始数组执行的特定测试的所有元素创建。

    var landSum = data.reduce(function(sum, d) {
      return sum + d.land_area;
    }, 0);
    console.log(landSum);
    

    reduce 的第一个参数是回调函数,它将返回减少的运行“总数”。此函数传入上次调用回调时返回的上一个值。在这里,该参数 - sum 提供了我们在数组中移动时的总和。回调 d 的第二个参数是我们正在处理的数组的当前值。

    reduce 可以取一个初始值,它是reduce 调用的第二个参数。对于这个例子,我们从 0 开始求和。如果没有提供起始值,那么对于回调的第一次执行(当没有前一个值时)回调的第一个参数将是第一个元素的值数组,减少从第二个元素开始。

    因此,在您的情况下,您将变量作为返回值传递给 reduce,这就是获得上述结果的原因

    【讨论】:

      猜你喜欢
      • 2020-08-07
      • 1970-01-01
      • 2017-11-06
      • 1970-01-01
      • 2020-08-05
      • 1970-01-01
      • 2015-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多