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?
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.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Description
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}
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 )