DEV Community

Pachi 🥑
Pachi 🥑

Posted on

Explain REDUCE Like I'm Five

I can't get reduce.
I mean, I got it's general idea, but at the same time I feel like I don't know anything at all x.x

So maybe explain it like I am 4 and a half :p

Top comments (19)

Collapse
 
brnkrygs profile image
Brian Krygsman

Hi!

First post on this awesome site, hope you don't mind a late response... (this is a fantastic question :) )

My favourite way of thinking about reduce is that its useful for changing the shape of a collection.

Why might changing the shape of a collection be useful?

Some reasons:

1. You want to collapse a collection of values into a single one

The classic example here is calculating a sum of a collection of numbers:

Turn [1,2,3,4] into 10.

by using reduce like this (as seen in the comment above):

[1,2,3,4].reduce(( sum, item ) => sum+=item, 0 );

2. You want to collect a list of records under a shared category

This case is a little more real-world - you have a collection of records that you need to group or categorize in some way for display or calculation, which means you might need to add a nesting level.

That is, turn this:

[
  { id: 1, category: 'fruit', name: 'Apple' },
  { id: 2, category: 'vegetable', name: 'Carrot' },
  { id: 3, category: 'grain', name: 'Oats' },
  { id: 4, category: 'fruit', name: 'Pear' }
]

Into this (notice the new nesting level... and its a dictionary now, not an array!):

{
  'fruit': [
    { id: 1, category: 'fruit', name: 'Apple' },
    { id: 4, category: 'fruit', name: 'Pear' }
  ],
  'vegetable': [
    { id: 2, category: 'vegetable', name: 'Carrot' }
  ],
  'grain': [
    { id: 4, category: 'fruit', name: 'Pear' }
  ]
}

By using reduce like this:

const products = [
  { id: 1, category: 'fruit', name: 'Apple' },
  { id: 2, category: 'vegetable', name: 'Carrot' },
  { id: 3, category: 'grain', name: 'Oats' },
  { id: 4, category: 'fruit', name: 'Pear' },
];

const categorizedProducts = products
  .reduce(( currentCollection, item ) => {

    // Check if we have this key or not. If not, initialize a child array
    if( !currentCollection[item.category]){
      currentCollection[item.category] = [];
    }

    // Collect this item under the right category
    currentCollection[item.category].push( item );

    // Continue building on this collection
    return currentCollection;
  }, {});

(feel free to play with it here: repl.it/@brnkrygs/Exploring-Reduce)

As others have noted, you can use reduce to implement map and filter as well, and you might be able to see how...

When you reduce a collection and push each item directly onto your result collection (or "accumulator"), but change just that item in some way, it's a map (e.g. capitalize the name of each item).

When you reduce a collection and inspect each item to decide if you want to push it onto your result collection or skip it, that is filter.

So...

  1. reduce changes the shape of the collection as a whole
  2. map changes individual items in a collection
  3. filter excludes individual items from a collection
Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

I use it when I want to do something on an array and get a single value in return.

const totalCost = foodItems.reduce((total,item) => total + item.cost, 0)
Enter fullscreen mode Exit fullscreen mode

Here I want to calculate totalCost (a single value)

so in this we are returning total + item.cost in every iteration, Whatever you return gets stored in the first parameter (total in this case) and you can use this stored value in next iterations.

Next parameter inside the callback function (item in this case) is the one value from an array which changes in every iteration

the 2nd parameter in the reduce function (0 in this case) is the initial value of total.

so lets say you want an object in return in that case you can do

const coolObj = coolArr.reduce((obj,item) => something something, {})
Enter fullscreen mode Exit fullscreen mode

(Sorry I'm on my phone right now I'll try to explain better in the morning.)

Collapse
 
thepeoplesbourgeois profile image
Josh

I'm always doing these things from my phone 😶

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻

haha I hate typing from phone

Thread Thread
 
thepeoplesbourgeois profile image
Josh

It's not great, but it goes a lot more smoothly when you turn off autocorrect. All of the operating systems have native swipe-to-type now, too, which obviates most of the unpleasantness. At least, when you're not on one of those gargantuan "Plus" phones >.>

Collapse
 
saurabhdaware profile image
Saurabh Daware 🌻 • Edited

I will suggest to try out Array Cardio chapter from JavaScript 30 :D

Collapse
 
vonheikemen profile image
Heiker • Edited

Maybe an image can help.
map-reduce-sandwich.

The interesting thing about reduce is that it can change the shape of the return value. In this sandwich example the cook could go out and trade the ingredients for a sushi and give you that. The responsability is on the cook (the reducer function).

So i guess that you can think of reduce like a restaurant where you have to bring the ingredients and the chef if you want to eat something. While preparing the food you pass each ingredient one by one to the chef, they do their thing and in the end hopefully you get a meal.

Collapse
 
hasnayeen profile image
Nehal Hasnayeen

As the name suggest reduce decrease items in a collection and return just a single item. Lets say someone gave you a basket full of oranges. Now you're not interested in the basket and orange all you want is orange juice. So you use a reduce machine and dump all the orange in the machine and now the machine take a orange at a time and then peel the outer skins of the orange, remove any seeds and squeezes all the juices from it and collect it in a jar and keep doing it until no orange is left and you're left with a jar of orange juice. Bon Appétit

Collapse
 
eaich profile image
Eddie • Edited

Explanation 1
You're on Netflix deciding which movie to watch. You narrow it down to 3 options. You go through each movie and read the summary. Ultimately, you select a movie based on your criteria - let's say duration because it's 11 PM and you want to go to sleep at some point.

You just executed a function on each movie (read the summary, read the duration) and then selected a movie based on your criteria.

Explanation 2
You found an old box of toys in your garage and decide to start selling them online. You pull out a toy one a time and decide how much you want to sell it for. You write down the price on a notebook. You do this for every single toy. At the end, you have a sum total of how much you could potentially make if you sell all of your toys.

You just executed a function on each toy (looked at it, determined how much you want to sell it for) and then at the end, you received a value of how much you could potentially make.

Collapse
 
devslewis profile image
Seth

The first explanation sounds a lot more like filter. You are more passing a function there that is checking if something is true or not. (Like is it interesting) and returning the one that passed.

Collapse
 
vonheikemen profile image
Heiker

But think about this: you could implement filter using reduce.

Collapse
 
eaich profile image
Eddie • Edited

Ah that's true and good catch. I was thinking more along the lines of determining how long a movie is based on the current time and how long it would keep you up. Ignore explanation 1!! =)

Collapse
 
thepeoplesbourgeois profile image
Josh • Edited

You can use reduce anywhere you could use a for or forEach loop. The main thing to understand about it is that what you return within it will be held onto for the next iteration, until you get through the entire collection you're reducing. You can actually implement map, filter, and forEach as variations of reduce, if you want to!

const map = (iterable, fn) => [...iterable].reduce((arr, item) => {
  arr.push(fn(item))
  return arr
}, [])

const filter = (iterable, fn) => [...iterable].reduce((arr, item) => {
  if (fn(item)) arr.push(item)
  return arr
}, [])

const forEach = (iterable, fn) => [...iterable].reduce((_, item) => { fn(item) }, null)

The most common example of a reduce is to sum a bunch of numbers, but you can also use it to join things as strings …

const join = (arr, separator = ",") => 
  arr.reduce((string, item, index) => string + 
    `${typeof item === "object" ? JSON.stringify(item) : item}` + 
    (index === arr.size - 1 ? "" : separator)
  )

Or you can use it to do a simple (naïve) reverse!

const reverse = (iter) => [...iter].reduce((rev, item) => {
  rev.unshift(item)
  return rev
}, [])

The essential thing to remember: reduce is basically for, only more FP about it.

Collapse
 
akashgiri profile image
Akash Giri

Hey, I don't know but did you check MDN guide/docs on Reduce. See the section How reduce() works and Examples, they are really good and they explain like you're five. I had hard time understanding higher order Array functions. But MDN docs are really good at explaining by example and explaining core concepts as well.

Collapse
 
pachicodes profile image
Pachi 🥑

Thank you, I tried that already, MDN never gets into my brain x.x

Collapse
 
svenvarkel profile image
Sven Varkel

In short reduce means reducing an array full of numbers down to a single number:)