My favorite uses for Array.prototype.reduce

My favorite uses for Array.prototype.reduce

My favorite uses for Array.prototype.reduce

I love `Array.prototype.reduce()`. I love the power and flexibility it brings me. Unfortunately, this Array prototype method confuses many developers, and as a result, isn’t used as often as it probably should be.

Before diving into the many uses for this Array prototype method, let’s take a look at the function signature.

Array.prototype.reduce(reducerFunction, startingValue);

And the reducerFunction signature looks like so:

function reducerFunction(accumulator, currentValue, currentIndex, sourceArray);

Let’s try to shed away some of the confusing terminology. I’ll be honest. When I was first started learning about this stuff it certainly made this function seem really intimidating and complicated. `Array.prototype.reduce()` is an iterator, in the same category as `filter()`, `map()`, `forEach()`, `some()`, `every()`, and many others. It’s a glorified `for` loop that does something with each item of the array.

Many of the uses for `reduce()` involve making something smaller, thereby “reducing” it to something less than it was. This often times includes changing the array to a different data structure altogether.

Looking at the `reduceFunction`, you’ll see that there is an `accumulator` argument. This is what really makes `reduce()` so special, because it comes with a built in a way of slowly building up a value without needing to instantiate another variable. Instead, you slowly modify the `accumulator` value, which starts as `startingValue`. The `accumulator` is slowly “accumulating” changes with each iteration.

Flatten an array

const comments = things.reduce((accumulator, thing) => {
  return accumulator.concat(thing.nestedThingArray)
}, []);

Quick sum or average

const total = [1, 2, 3, 4, 5].reduce((accumulator, item) => {
  return accumulator + item;
}, 0);

const average = [1, 2, 3, 4, 5].reduce((accumulator, item, itemIndex, sourceArray) => {
  if (itemIndex === sourceArray.length - 1) {
    return (accumulator + item)/sourceArray.length;
  }
  return accumulator + item;
}, 0);

Create a dictionary

Let’s say you’re needing to find specific objects in an array over and over again, perhaps in another loop. You can easily get into O n^2 territory or beyond. One real easy optimization to get you back into linear complexity land is to create a dictionary keyed off of the value you are looking for in the array.

const things = [
  { id: 'a', otherThings: { nested: "deep" } },
  { id: 'b', moreThings: { nested: "somewhere" } },
  { id: 'c', evenMoreThings: { nested: "beyond" } }
];

things.reduce((acc, thing) => {
  acc[thing.id] = thing;
  return acc;
}, {});

Count things

[
  { type: 'A' },
  { type: 'A' },
  { type: 'B' }
].reduce((acc, item) => {
  if (!acc[item.type]) {
    acc[item.type] = 0;
  }
  acc[item.type] += 1;
  return acc;
}, {});

Transform array to some other complicated structure

No need for an example here, but you could use `reduce()` to change an array structure to just about any other complicated structure you can think of.

Leave a Reply

Your email address will not be published. Required fields are marked *