【问题标题】:A question on JavaScript .reduce method's accumulator关于 JavaScript .reduce 方法的累加器的问题
【发布时间】:2020-08-15 03:53:28
【问题描述】:

我正在解决这个问题,以使用 reduce 方法创建一个函数,该函数将获取数组中的最大数。

导师的回答是:

const numbers = [1, 2, 3, 4, 4, 5, 1, 3, 4];
const max = getMax(numbers);
console.log(max);
function getMax(array) {
   if (array.length === 0) return undefined;
   return array.reduce((accumulator, current) => {
       return (accumulator > current) ? accumulator : current
}); 

我试过这样的:

 return array.reduce((accumulator, current) => {
    if (accumulator < current)
        console.log(accumulator, current);
        return accumulator = current;
});   

我添加了 console.log (accumulator, current),因为我想看看我的代码发生了什么。日志显示如下:

console.log of my code

1 2
2 3
3 4
4 5
1 3
3 4
4

问题 1。我想知道为什么我的函数没有给出正确的输出(它返回 4,而不是正确的输出 5)。 “累加器”在循环期间被分配为 5 时不应该保持 5 吗?

问题2.为什么在if语句下面已经有return的情况下,函数中还需要return(或者前面加return)?

【问题讨论】:

  • 欢迎来到 SO! Math.max(...nums) 肯定更容易。您的 reduce 版本没有多大意义——return 语句中的赋值并没有真正实现任何目标,并且 accumulator 和 current 永远不会改变——console.log 是有条件地记录的。在函数结束之前避免使用console.log——这可能会造成混乱。
  • 您没有在if 语句之后使用{ ... },因此只有第一行console.log(...) 在满足条件时发生。 accumlator = current 行总是在每次迭代中出现。使用命令式 if statement 时必须使用 return。但是,当使用函数式表达式时,您可以跳过return,即(accumulator, current) =&gt; accumulator &lt; current ? current : accumulator,它表示“如果累加器小于当前值,则返回当前值,否则返回累加器”
  • (accumulator &gt;=current) 时的返回值是什么?没有,所以累加器是空的
  • @ggorlen 提到“讲师”我认为练习的重点是编写自己的代码来学习 reduce 或 lambdas 或类似的东西,而 Math.max() 不会允许。
  • 谢谢大家 - 你能回答我的问题 #2,你可能已经回答了,但我仍然不确定我是否理解。 @谢谢你

标签: javascript arrays reduce accumulator


【解决方案1】:

您没有在if 语句之后使用{ ... },因此只有第一行console.log(...) 在满足条件时发生。 accumlator = current 行总是在每次迭代中出现。在使用命令式 if 语句 时,您必须使用 return。但是,当使用函数式表达式时,您可以跳过return,即(accumulator, current) =&gt; accumulator &lt; current ? current : accumulator,它表示“如果累加器小于当前值,则返回当前值,否则返回累加器”

考虑这个分解的程序。当我们将max 视为一个独立的函数时,它可以帮助我们准确地看到reduce 所期望的函数类型 -

const max = (a = 0, b = 0) =>
  a < b               // if a is less than b
    ? b               // return b
    : a               // otherwise return a
 
const getMax = (numbers = []) =>
  numbers.length === 0          // if numbers.length is zero
    ? undefined                 // return undefined
    : numbers.reduce(max)       // otherwise return reduction

console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5

console.log(getMax([]))
// undefined

console.log(getMax())
// undefined

我们可以看到reduce正在产生以下计算-

// given
[1, 2, 3, 4, 4, 5, 1, 3, 4]

// starting with the first two
r = max(1, 2)

// then the next number
r = max(r, 3)

// then the next number
r = max(r, 4)

// then the next number
r = max(r, 4)

或者没有中间r = ... -

max(max(max(max(max(max(max(max(1, 2), 3), 4), 4), 5), 1), 3), 4)

如果我们愿意,我们可以写getMax 而不写reduce -

const max = (a = 0, b = 0) =>
  a < b
    ? b
    : a
 
const getMax = (numbers = []) =>
  numbers.length === 0 // without any numbers,
    ? undefined        // there can be no max.
: numbers.length === 1 // if we only have one,
    ? numbers[0]       // we already know max.
    : max(numbers[0], getMax(numbers.slice(1))) // else

console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5

console.log(getMax([]))
// undefined

console.log(getMax())
// undefined

或者你可能还没有学过slice。您可以使用数组索引i 来遍历您的数组 -

const max = (a = 0, b = 0) =>
  a < b
    ? b
    : a
 
const getMax = (numbers = [], i = 0) =>
  numbers.length === 0    // without any numbers,
    ? undefined           // there can be no max.
: i + 1 >= numbers.length // if the next i is not in bounds,
    ? numbers[i]          // this is the last number
    : max(numbers[i], getMax(numbers, i + 1)) // else

console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5

console.log(getMax([]))
// undefined

console.log(getMax())
// undefined

解构赋值也可以使用-

const max = (a = 0, b = 0) =>
  a < b
    ? b
    : a
 
const getMax = ([ num, ...more ] = []) =>
  more.length === 0
    ? num
    : max(num, getMax(more))
    
console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5

console.log(getMax([]))
// undefined

console.log(getMax())
// undefined

这可能会告诉你如何发明自己的reduce -

const max = (a = 0, b = 0) =>
  a < b
    ? b
    : a
 
const reduce = (f, a = [], i = 0) =>
  a.length === 0    // without any numbers,
    ? undefined     // there can be no reduction.
: i + 1 >= a.length // if the next i is not in bounds,
    ? a[i]          // this is the last element
    : f(a[i], reduce(f, a, i + 1)) // else

const getMax = (numbers = []) =>
  reduce(max, numbers) // <-- our reduce!

console.log(getMax([1, 2, 3, 4, 4, 5, 1, 3, 4]))
// 5

console.log(getMax([]))
// undefined

console.log(getMax())
// undefined

【讨论】:

  • 或者干脆const getMax = (arr=[]) =&gt; arr.reduce((a,c)=&gt;(a&gt;c)?a:c,undefined)
  • 不,没有那么简单,莫乔先生。 a = undefined 在 reducer 的第一次迭代中,所以你在做 undefined &gt; ... 这是一个无效的比较。
  • 您同意const max1 = (a, b) =&gt; a &gt; b ? a : bconst max2 = (a, b) =&gt; a &lt; b ? b : a 相同吗?现在你能解释为什么numbers.reduce(max1, undefined) 返回5numbers.reduce(max2, undefined) 返回undefinedmax1max2 对于所有 xy 都是相同的。 max1 不是“完美”地工作,而是靠运气。碰巧在 JavaScript 中 undefined &lt; x 为所有 x 返回 false,所以 max1 偶然发现了正确的答案。
  • 不,不一样。如果a===undefineda &gt; b ? a : b 返回ba &lt; b ? b : a 返回a;与 undefined 的任何比较都返回 false,这正是我创建 a &gt; b 而不是 a &lt; b 的原因。这不是一个愚蠢的运气。
  • 当你给两个相等的函数一个 undefined 输入你得到一个 undefined 输出......你犯了将undefined传递给@的错误987654371@ 或 &lt; (或其他),所以现在你不能依赖结果!函数式编程就是要避免这样的意外。程序员可以给你max1max2,两个答案都是正确的。但是,当它们用于 reduce 时,以您使用 undefined 应用的特定方式,您会为每个函数获得不同的结果。这种错误是最糟糕的,因为不清楚问题出在哪里。
【解决方案2】:

尝试使用 Math.max 方法:

const numbers = [1, 2, 3, 4, 4, 5, 1, 3, 4]
numbers.reduce((acc, rec) => Math.max(acc, rec))

//5

function max(numbers) {
  return list.reduce((acc, rec) => acc > rec ? acc : rec)
}

如果您需要在没有 Math.max 的情况下找到最大值。

【讨论】:

  • 只需做Math.max(...numbers)
  • Math.max 使用数字,但输入的是数字数组,所以我决定将此方法与 reduce 结合使用。
  • 是的,你选择在最小值处使事情复杂化
猜你喜欢
  • 1970-01-01
  • 2021-12-12
  • 1970-01-01
  • 2018-11-21
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 2020-12-02
  • 1970-01-01
相关资源
最近更新 更多