使用Reduce将数组转换为Object

时间:2016-08-17 08:30:22

标签: javascript functional-programming

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

学习使用 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)

6 个答案:

答案 0 :(得分:3)

reduce的工作方式与mapfilter非常相似。在这种情况下,reducer负责将对象数组减少到一个对象中。

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

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

有关详细信息,请转到here

答案 1 :(得分: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/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

更多示例和简要说明:

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

答案 2 :(得分:1)

我在您的代码中插入了一些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));




答案 3 :(得分:1)

这里和其他地方有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 ]
]

仅适用于乐趣

我可以通过编写构建字符串的reducer而不是实际添加数字来表明通过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时,此技术可能对您有用

答案 4 :(得分:0)

reduce()方法将数组降低为单个值

reduce()方法执行 提供的函数,用于数组的每个值(来自左到右)。

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

您有给定列表

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

然后你制作一个初始列表您可以修改此功能,该功能将应用于两个列表。

var initialValue = {}

"减速器"被初始化为函数我们将函数放在" 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)

答案 5 :(得分:0)

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

执行时

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 ...
...