Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to access zeroth element in reduce to count repeats in an array

On the whim of node school, I am trying to use reduce to count the number of times a string is repeated in an array.

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}

is sort of working. For some reason, reduce seems to skip the first element. I don't know why. Its first time through the array, index is 1. I tried putting in some logic like, if (index === 1){//put 'prev' as a property of 'obj'}. But that seems really convoluted. I'm certain that this is not how node school wants me to solve this problem. However, I wonder what's a good way to access the zeroth element in the array you're reducing. Why is this zeroth element seemingly ignored by the reduction procedure? I guess I could pass in fruits[0] after the callback so I start with that value initially. What's the best way to access this zeroth element?

like image 958
1252748 Avatar asked Jul 16 '15 22:07

1252748


People also ask

How do you count the number of repeats in an array?

To count the duplicates in an array: Declare an empty object variable that will store the count for each value. Use the forEach() method to iterate over the array. On each iteration, increment the count for the value by 1 or initialize it to 1 .

How do you get rid of repeating elements in an array?

To remove duplicates from an array: First, convert an array of duplicates to a Set . The new Set will implicitly remove duplicate elements. Then, convert the set back to an array.

How do you count the number of times an element appears in an array?

To check how many times an element appears in an array:Declare a count variable and set its value to 0 . Use the forEach() method to iterate over the array. Check if the current element is equal to the specific value. If the condition is met, increment the count by 1 .


2 Answers

The syntax of reduce() is:

arr.reduce( callback [, initial] );

If you omit initial value, callback will get called 5 times, with arr[0] passed in as the initial value of previous:

callback( previous=arr[0], current=arr[1], index=0, array=arr );
callback( previous       , current=arr[2], index=1, array=arr );
callback( previous       , current=arr[3], index=2, array=arr );
callback( previous       , current=arr[4], index=3, array=arr );
callback( previous       , current=arr[5], index=4, array=arr );

If you include initial value, callback will get called 6 times with initial passed in as the initial value of previous:

callback( previous=initial, current=arr[0], index=0, array=arr );
callback( previous        , current=arr[1], index=1, array=arr );
callback( previous        , current=arr[2], index=2, array=arr );
callback( previous        , current=arr[3], index=3, array=arr );
callback( previous        , current=arr[4], index=4, array=arr );
callback( previous        , current=arr[5], index=5, array=arr );

Because you're building an object, I recommend you passed in an empty object { } as the initial value:

function reduceFunction(previous, current, index, array) {
    // console.log("debug: ", " current: ", current, "index: ", index);
    if (!previous[current])
        previous[current] = 1;
    else
        previous[current]++;
    return previous;
}

const initial = { };
const fruits = [ "Apple", "Banana", "Apple", "Durian", "Durian", "Durian" ];
const result = fruits.reduce( reduceFunction, initial );
console.log( "result: ", result );

// Output:
//
// result:  {
//   "Apple": 2,
//   "Banana": 1,
//   "Durian": 3
// }

Reference:

  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
like image 102
Stephen Quan Avatar answered Oct 10 '22 02:10

Stephen Quan


If no initialValue was provided, then previousValue will be equal to the first value in the array and currentValue will be equal to the second.

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

Additionally, you have to return a value from the function. That value becomes the value of previousValue on the next iteration.

I'd suggest you "carry" your aggregator obj as the initial value.

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));

Here's a simple diagram:

               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}
like image 39
Joseph Avatar answered Oct 10 '22 01:10

Joseph