深入减少()

Reduce() in depth

在 ES5 中,新的数组方法 reduce()。我想知道是否有人可以更深入地解释。

var test = [1, 2, 3, 4, 5].reduce(function(inital, item, idx) {
  return inital + item
}, 0);

console.log(test);

在这个例子中,我们知道初始参数为0并通过回调函数循环。有人可以向我解释初始参数的范围吗?

如果我们假设 [1, 2, 3, 4, 5] 是 return 从假想的方法中编辑出来的,并且想要 return 一个对象形式,其键是 idx 和值是 Math.pow(idx,2)。 {1:1, 2:4, 3:9, 4:16, 5:25}。有人可以向我解释一下吗?

还有 :) 我们有一个字母数组。有些重复有些不重复。我想计算一个数组中有多少个字母并将其转换为对象形式。 {a:5, .... z:7}; 有人请引导我完成它。我理解 forEach 和 map 很好,但是使用 reduce 方法,我很难理解它。

提前致谢

您传递给 .reduce 的方法采用参数 previous_returned_value, current_iteration_item, current_iteration_index, context_array

这意味着每次调用时,第一个参数是上次调用的return

初始值是第一次传入的值。

您可以阅读 MDN docs about it here


return an object form which key is idx and value is Math.pow(idx,2)

  • 您传入一个初始的空对象
  • 您的方法向该对象添加了属性
  • 方法return对象

例如

 [1, 2, 3, 4, 5].reduce((o, e) => (o[e] = Math.pow(e, 2), o), {});
 // Object {1: 1, 2: 4, 3: 9, 4: 16, 5: 25}

count how many letters are are in an array and turn it into the object

  • 再次传入一个初始的空对象
  • 方法sets/adds1根据当前字母到对象
  • 方法return对象

又是这样

['f', 'o', 'o', 'b', 'a', 'r'].reduce((o, e) => (o[e] = (o[e] || 0) + 1, o), {});
// Object {f: 1, o: 2, b: 1, a: 1, r: 1}

请注意我使用的箭头符号函数利用逗号运算符 return 我想要的,更传统的是你可以将函数写成例如随后演变为我的例子

function (o, e) {
    o[e] = Math.pow(e, 2);
    return o;
}
// same as
function (o, e) {
    return o[e] = Math.pow(e, 2), o;
}
// similar to
(o, e) => {
    return o[e] = Math.pow(e, 2), o;
}
// same as
(o, e) => (o[e] = Math.pow(e, 2), o);

假设我们的应用程序中某处有以下代码片段:

function addLog() {
  console.log(arguments)
  return arguments[0] + arguments[1]
}

console.log([2,3,4].reduce(addLog))
console.log([2,3,4].reduce(addLog, 1))

不幸的是,我们依赖于一个名为 badlibrary.js 的库,它将覆盖 ES5 的默认 Array.prototype.reduce:

badlibrary.js:

Array.prototype.reduce = Infinity

由于该库是我们应用程序的依赖项,因此我们无法删除该库。唯一的解决办法是在 运行 我们的代码之前通过重写来修复 Array.prototype.reduce

原来这并没有那么难。我们可以只阅读 Mozilla's documentation on reduce 并将英文翻译成 JavaScript.

Array.prototype.reduce = function(callback, initialValue) {
  var resultSoFar, i
  var n = this.length
  if (typeof initialValue !== 'undefined') {
    resultSoFar = initialValue
    i = 0
  } else {
    resultSoFar = this[0]
    i = 1
  }
  for (; i < n; i++) {
    resultSoFar = callback(resultSoFar, this[i], i, this)
  }
  return resultSoFar
}

我们的代码现在可以工作了,即使使用这个自定义版本的 reduce,现在 reduce 不再是 "black box"。如果我们愿意,我们可以很容易地自己编写它,事实上,在 ES5 标准化之前,这就是几个人所做的。顺便说一下,有些人仍然 使用最多只支持 ES3 的浏览器。为了使 reduce 真正实现跨浏览器兼容,我们仍然需要填充它或使用像 Underscore/Lodash/Ramda 这样的实用程序库。使用实用程序库是 IMO,最好和最简单的解决方案。

ALSO :) we have an array with lettters. some repeats some don't. I want to count how many letters are are in an array and turn it into the object form. {a:5, .... z:7}; Someone please walk me through with it. I understand forEach and map just fine, but with the reduce method, I am having very difficult time getting my head around it.

我们想要的东西 return 是一个 JS 对象,其中字母作为键,它们的计数作为值。我们在 reduce 函数中调用了这个值 resultSoFar 并且我们将通过对数组的每个元素调用我们的函数来构建该值。我们的初始值应该是一个空对象。在我们的函数中,我们将获取当前字母并尝试将其计数加 1。如果这产生 NaN (如果计数未定义,即当我们第一次看到一个字母并且尚未分配计数时会发生这种情况),那么我们应该将值分配给 1 因为它是一个新的信来计数,我们正在看到其中之一。

有了这个理论,计数代码可以这样写:

var letters = ['a', 'b', 'c', 'a', 'b', 'a']
console.log(letters.reduce(function(counts, currentLetter) {
    var currentLetterCount = counts[currentLetter]
    counts[currentLetter] = currentLetterCount + 1 || 1
    return counts
  }, {}))

reduce() 方法是一个迭代器,它遍历数组中的所有元素并对结果进行处理。 reduce() 函数接受回调函数。这个函数在每次迭代中实际执行你想要它做的任何事情。此函数为特殊函数

这个函数接受的第一个参数是以前的值 这个函数的第二个参数是当前值 和其他两个参数(让这个简单一点)

假设我们有一个数组

arr=[1,2,3,4,5,6]

通过创建一个名为 sum

的函数来使用 reduce
function sum(previousvalue,currentvalue,index,ar){
return previousvalue+currentvalue
}

最后我们在 reduce 方法中放置这个函数的引用

arr.reduce(sum)

执行这个我们得到 21

这个特殊功能到底在做什么? 让我们考虑一下

[1,2,3,4,5,6]

函数总和表示

Wrong! "let me take the current element value in this array " == 1


Right! # the function starts at the second element in the array so the previous element is the 1st element

 "let me add the current element value to the prev. element value in this array and remember this value " == 1+2


"okay I am moving on to the next value"==3

"okay..I will add the next value to the previous summed up value"==3+3
"now I will save this value and do the same thing again until I loop to the end"

但是等等这个有什么实际用处,我不用reduce函数也能轻松写出来?

它就像一个生成器函数(就像在某些语言中一样,例如 python)..它不记住除了先前调用值和当前值之外的值...(一些内存效率优势)

例子 寻找移动平均线

   function sum(previousvalue,currentvalue,index,ar){
    return (previousvalue+currentvalue/2)
    }

上面的函数是我使用的相同旧函数的修订版

-取前两个元素求平均值并保存值 - 它需要下一个元素加上它的平均值并找到另一个平均值并且循环继续