All things Software Dev & Architecture

All things Software Dev & Architecture

Counting items in a JavaScript Array with reduce

The simplicity of the reduce method

Subscribe to my newsletter and never miss my upcoming articles

I am a functional programming fan, and I strive for purity and simplicity wherever I can. I especially love the challenge of doing something as simple as succinctly as possible without the cost of bloated code. JavaScript's implementation of reduce is a wonderful and flexible tool that allows expression on this level.

Recently I read a post that provided a solution to counting the occurrences of an item in an array, which to me was ugly, bloated, and impure, it mutated the original array and contained unnecessary code overhead. I immediately thought I can do this is far less code and with far less overhead, with reduce, not only does this allow a cleaner approach but it can be done in about 95% less code!

I decided to go use the object property assignment approach to counting items, this is a simple idea that creates an object as a look-up table for items, where the keys are the items and the values the counts. With reduce, I can pass an empty object in as the accumulator, the return value from the function is the populated object, which could be then passed on to be used to calculate the most frequent item for example.

Here's the code, it uses a simple array of primitive strings, but could be adapted to use objects easily without any change to the signature, Such is the beauty of reduce().


/* Keep a record of the count of each item in the array */

const fruits = ["apples", "oranges","pears","bananas","pears","melons","apples","apples"]

const counts = fruits.reduce((accumulator, current) => {
   accumulator[current] = accumulator[current]
        ? accumulator[current] +=1 
        : accumulator[current] = 1
   return accumulator
},{})

console.log(counts)

/*  Result
{
  apples: 3,
  bananas: 1,
  melons: 1,
  oranges: 1,
  pears: 2
}

*/

OK, this is fairly contrived but, let me walk through it.

  1. The Array

    const fruits = ["apples", "oranges","pears","bananas","pears","melons","apples","apples"]
    
  2. Reduce signature

    fruits.reduce((accumulator, current)=>{},{})
    

The accumulator is a running total, the current is the current item in the iteration. There are more parameters here if needed, such as the index in the array and the array itself, but we don't need those. The final `{} is the default accumulator value, to begin with, in this case, an empty object.

  1. Expression
 accumulator[current] = accumulator[current]
        ? accumulator[current] +=1 
        : accumulator[current] = 1
  return accumulator

Here we are assigning accumulator[current] a value. Since the accumulator is simply an empty object we are assigning the object with a property of the current value. So the first item in the array so we are saying. accumulator['apples'] = #someValue which is basically { apples: #someValue }.

Next, we have to check if the accumulator['apples'] has a value because if it doesn't the following value assignment of adding a number will fail with a NaN (not a number error). If it has a value, it's not the first occurrence in the array, and it's another occurrence, which means we can just increase the value by 1. If it has no value then give it the value of 1 since it's the first occurrence in the array. The syntax we use is known as a ternary conditional operation, it's a shortcut expression that for an if-else condition

reference = (an expression that must be truthy or falsely ) ? expression if true : expression if false

In my example I am putting the true and false expressions on separate lines for clarity, it could be on one line.

This is the same as saying

let reference;
if(expression that is truthy or falsey) {
  reference = #someValue
} else {
    reference = #someOtherValue
}

We then finally return the accumulator to the iteration. Reduce then returns to the assignment once there are no more current values.

...
return accumulator

Reduce is a very powerful construct and generally misunderstood. I've noticed that many posts online omit reduce when talking about array functions in javascript but they shouldn't. On a more interesting note, map, filter and reduce are the foundational functions in javascript for functional programming They are non-destructive to the original array and take other functions as parameters. Key features for FP. I hope you enjoyed this, let me know your thoughts.

 
Share this