繁体   English   中英

使用Reduce将数组转换为对象

[英]Converting Array to Object using Reduce

有人可以解释这是如何工作的。

学习使用Array.reduce()

var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'];

var initialValue = {}

var reducer = function(tally, vote) {
  if (!tally[vote]) {
      tally[vote] = 1;
  } else {
      tally[vote] = tally[vote] + 1;
  }
      return tally;
  }

var result = votes.reduce(reducer, initialValue)

reduce的工作方式与mapfilter非常相似。 在这种情况下,reducer负责对象数组简化为一个对象。

reducer函数遍历数组的所有元素。 该函数使用两个参数调用, tally 到目前为止减少的结果当前正在处理的 vote 数组元素

如果tally没有像当前正在处理/缩减的元素那样命名的属性,则它将这样的键添加到对象并将其值设置为1。 否则(存在密钥),它将增加一。

欲了解更多信息,请点击这里

基本上, Array.prototype.reduce()方法对一个累加器和数组的每个值应用一个函数,以将其减少为单个值。

在您的示例中,将减小的值(计数操作的结果)分配为称为tally的对象的属性,该对象由.reduce()返回;

我用简短的解释评论您:

 // your data in an array var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza']; // optional value to use as the first argument to the first call of the callback when using Array.prototype.reduce(). var initialValue = {} // tally = previousValue and vote = currentValue var reducer = function(tally, vote) { // if tally is not assign as a key in tally object, add key and add value of one, (basically count 1 for one element in your votes array) if (!tally[vote]) { tally[vote] = 1; } else { // otherwise if tally object has already this key, increment its value by one, (basically it counts how many times each item in votes array is present in the array) tally[vote] = tally[vote] + 1; } return tally; } var result = votes.reduce(reducer, initialValue); console.log(result); 

注意:实际上,您可以避免使用为initialValue声明变量,而只使用var result = votes.reduce(reducer, {});

API文档:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

更多示例和简要说明:

https://www.airpair.com/javascript/javascript-array-reduce

我在您的代码中插入了一些console.log消息,这有助于我了解发生了什么。

 var votes = ['tacos', 'pizza', 'pizza', 'tacos', 'fries', 'ice cream', 'ice cream', 'pizza']; var initialValue = {} var reducer = function(tally, vote) { console.log("tally: ", tally); console.log("vote: ", vote); console.log("tally[vote]: ", tally[vote]); if (!tally[vote]) { tally[vote] = 1; } else { tally[vote] = tally[vote] + 1; } return tally; } var result = votes.reduce(reducer, initialValue) console.log("result: " + JSON.stringify(result)); 

在这里和其他地方有很多关于reduce的冗长解释,但我认为简单的视觉演示可能会有所帮助

[1,2,3].reduce(function(a,b) { return a + b }, 0)
// (((0 + 1) + 2) + 3)
// => 6

您可以看到:

  • 3个元素的输入列表将导致3次计算
  • 初始值用于第一个元素的计算
  • 一个计算的结果将在下一个计算中使用…
  • …直到最后的计算,这是reduce的结果

现在,对于您的代码,我们并没有建立数字的总和,而是建立了一个Object ,它保存数组中每个字符串的计数计数。

我没有必要解释其他所有人的所作所为,但这不足为奇,这并不奇怪,因为没有人解释这是对Object的滥用。

实际上,对于这种简化,对象实际上不是最佳的数据结构选择。 在这里,对象用于模拟Map的行为。

我们将initialValue设置为new Map()然后您将了解reducer如何在其中使用更多描述性语法。 注意注释甚至不是必需的,因为代码说明了它所需要的一切。

 var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'] var initialValue = new Map() var reducer = function (tally, vote) { if (tally.has(vote)) return tally.set(vote, tally.get(vote) + 1) else return tally.set(vote, 1) } var result = votes.reduce(reducer, initialValue) console.log(Array.from(result.entries())) 

输出量

[
  [ "tacos", 2 ],
  [ "pizza", 3 ],
  [ "fries", 1 ],
  [ "ice cream", 2 ]
]

只是为了好玩

我可以通过编写一个构造字符串而不是实际将数字相加的reduce来向您展示通过reduce进行的总和的视觉表示是正确/准确的

 var initialValue = 0 var reducer = function(a,b) { return '(' + a + ' + ' + b + ')' } var result = [1,2,3].reduce(reducer, initialValue) console.log(result) // (((0 + 1) + 2) + 3) 

尝试了解/调试自己的Reducer时,此技术可能对您有用

reduce()方法数组缩小单个值

reduce()方法为数组的每个值从左到右 执行 提供的函数

函数的返回值 存储在累加器中(结果/总计)。

您有此给定列表

var votes = ['tacos','pizza','pizza','tacos','fries','ice cream','ice cream','pizza'];

然后创建一个初始列表 您可以对此进行修改,并且该功能将同时应用于两个列表。

var initialValue = {}

“ reducer”被初始化为一个函数 之所以将函数放置在“ reducer”中,是因为我们可以更轻松地对其进行调用。 您可以在此函数中做任何您想做的事,它将在接下来的步骤中在列表中执行

var reducer = function(tally, vote) {
  if (!tally[vote]) {
      tally[vote] = 1;
  } else {
      tally[vote] = tally[vote] + 1;
  }
      return tally;
  }

最后,函数的结果 存储到变量中。

var result = votes.reduce(reducer, initialValue)

好吧,让我们尝试扩展迭代:

执行时

votes.reduce(reducer, initialValue)

它实际上是这样做的:

reducer(initialValue, votes[0]); // step1, return {'tacos': 1}
reducer(returnedValueOfStep1, votes[1]); // step2, return {'tacos': 1, 'pizza': 1}
reducer(returnedValueOfStep2, votes[2]); // step3, return {'tacos': 1, 'pizza': 2}
reducer(returnedValueOfStep3, votes[3]); // step4 ...
reducer(returnedValueOfStep4, votes[4]); // step5 ...
reducer(returnedValueOfStep5, votes[5]); // step6 ...
reducer(returnedValueOfStep6, votes[6]); // step7 ...
reducer(returnedValueOfStep7, votes[7]); // step8 ...

我认为现在很清楚。

通常,如果我们不提供initialValue作为reduce的第二个参数,它将数组的第一个元素作为initialValue,并从第二个元素开始迭代:

reducer(votes[0], votes[1]); // step1 ...
reducer(returnedValueOfStep1, votes[2]); // step2 ...
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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