如何在reduce中访问第0个元素以计算数组

时间:2015-07-16 22:16:54

标签: javascript node.js mapreduce

在节点学校的一时兴起,我试图用reduce来计算字符串在数组中重复的次数。

var fruits = ["Apple", "Banana", "Apple", "Durian", "Durian", "Durian"],
    obj = {};
fruits.reduce(function(prev, curr, index, arr){
   obj[curr] ? obj[curr]++ : obj[curr] = 1;
});
console.log(obj); // {Banana: 1, Apple: 1, Durian: 3}

有点正在工作。出于某种原因,reduce似乎跳过了第一个元素。我不知道为什么。它第一次通过数组,index1。我试着加入一些像if (index === 1){//put 'prev' as a property of 'obj'}这样的逻辑。但这似乎真的很复杂。我确定这不是节点学校希望我解决这个问题的方式。但是,我想知道什么是访问正在减少的数组中的第0个元素的好方法。为什么这个零级元素似乎被还原过程忽略了?我想我可以在回调后传递fruits[0]所以我最初从那个值开始。访问这个第0个元素的最佳方法是什么?

3 个答案:

答案 0 :(得分:11)

  

如果未提供initialValue,则previousValue将等于数组中的第一个值,currentValue将等于第二个值。

     

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Description

此外,您必须从函数返回一个值。该值在下一次迭代时变为previousValue的值。

我建议你“携带”你的聚合器obj作为初始值。

var fruits = ["Apple", "Banana", "Apple", "Durian", "Durian", "Durian"];
var obj = fruits.reduce(function(carry, fruit){
  if(!carry[fruit]) carry[fruit] = 0; // If key doesn't exist, default to 0
  carry[fruit]++;                     // Increment the value of the key
  return carry;                       // Return aggregator for next iteration
}, {});
alert(JSON.stringify(obj));

这是一个简单的图表:

               fruit  carry (before operation)      carry (after operation, returned value)
1st iteration: Apple  {}                            {Apple:1}
2nd iteration: Banana {Apple:1}                     {Apple:1, Banana:1} 
3rd iteration: Apple  {Apple:1, Banana:1}           {Apple:2, Banana:1}
4th iteration: Durian {Apple:2, Banana:1}           {Apple:2, Banana:1, Durian:1}
5th iteration: Durian {Apple:2, Banana:1, Durian:1} {Apple:2, Banana:1, Durian:2}
6th iteration: Durian {Apple:2, Banana:1, Durian:2} {Apple:2, Banana:1, Durian:3}

答案 1 :(得分:1)

reduce()的语法是:

arr.reduce(callback[, initialValue])

由于您未提供initialValuereduce()会将其作为第一个previousValue提供给您,然后为剩余的5个项目调用callback。如果您提供了initialValue,则reduce()会为所有6个项目调用callback

initialValue是您正在构建的obj。但是,您需要以reduce()的模式使用它。即,不要声明全局obj。将其作为initialValue传递。然后,在每次返回时,您必须返回该值的下一个版本。

reduce()最终将返回最终结果。



var fruits = ["Apple", "Banana", "Apple", "Durian", "Durian", "Durian"];
var result = fruits.reduce(function(previousValue, currentValue, index, array) {
    previousValue[currentValue] ? previousValue[currentValue]++ : previousValue[currentValue] = 1;
    return previousValue;
}, { } );
console.log(result);
alert(JSON.stringify(result));




答案 2 :(得分:0)

这个问题已经很老了,答案已经明确了。

此外,我还包含了官方文档中的描述,该描述还有其他要点,这将对新来者有帮助

From the official documentation of Array.prototype.reduce()

reduce()方法为每个分配的值执行一次回调 存在于数组中,带有四个参数:

  • 蓄能器
  • currentValue
  • currentIndex
  • 数组

第一次调用回调时,累加器和currentValue 可以是两个值之一。如果在调用中提供了initialValue reduce(),则累加器将等于initialValue,并且 currentValue将等于数组中的第一个值。如果不 提供initialValue,则累加器将等于第一个 数组中的值,并且currentValue将等于第二个。

注意:如果未提供initialValue,则reduce()将执行 从索引1开始的回调函数,跳过第一个索引。如果 提供了initialValue,它将从索引0开始。

如果数组为空且未提供initialValue,则TypeError将 被扔。

如果数组只有一个元素(与位置无关)而没有 提供initialValue,或者如果提供initialValue,但数组 为空,将返回solo值,而无需调用回调。

还有一点修改,

var fruits = ["Apple", "Banana", "Apple", "Durian", "Durian", "Durian"], obj = {};
fruits.reduce((prev, curr, index, arr) => {
   if(!prev.hasOwnProperty(curr)) {
       prev[curr] = 0;
   }
   prev[curr]++;
   return prev;
}, obj);
console.log(obj);