How to access zero element in shorthand to count repetitions in an array
On a whim of the school node, I am trying to use reduce
to count the number of repetitions of a string 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 a kind of work. For some reason reduce
, it seems to be missing the first element. I do not know why. Its the first time through the array, index
- 1
. I tried to introduce some logic like if (index === 1){//put 'prev' as a property of 'obj'}
. But it seems really confusing. I'm pretty sure this is not how the node school wants me to solve this problem. However, I wonder what a good way to access the zero element in the array you are decreasing. Why is this null element seemingly ignored by the pruning routine? I guess I could go through fruits[0]
after the callback to start at this value initially. What's the best way to access this null element?
source to share
If it was not
initialValue
, then itpreviousValue
will be equal to the first value in the array, but itcurrentValue
will be equal to the second.
Also, you must return the value from the function. This value becomes the value previousValue
in the next iteration.
I suggest that you "wrap" your aggregator obj
as a seed.
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}
source to share
Syntax reduce()
:
arr.reduce( callback [, initial] )
If you omit the initial
value, it callback
will be called 5 times and arr[0]
passed as the initial value 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 a initial
value, it callback
will be called 6 times with initial
the initial value passed in 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 )
Since you are building an object, I recommend passing an initial
empty object as the value { }
:
function reduceFunction(previous, current, index, array) {
console.log("debug: index: ", index, " current: ", current)
if (!previous[current])
previous[current] = 1
else
previous[current]++
return previous
}
const fruits = [ "Apple", "Banana", "Apple", "Durian", "Durian", "Durian" ]
const result = fruits.reduce( reduceFunction, { } )
console.log( "result: ", result )
source to share