markdown guide
 

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
 

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)

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, {})

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

 
 

I'm always doing these things from my phone 😶

 

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 >.>

 

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.

 
 

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.

 

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

 

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.

 

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.

 

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!! =)

 

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

 

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.

 

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

 

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

Classic DEV Post from Jan 30

Understanding Callbacks and Promises

These two concepts are basic things of the Javascript programming language. Because said language works under the paradigm of asynchronous programming.

Pachi //Pati (she/her/ela) profile image
Front-End; Code Newbie; Self-directed learner; Brasileira; Witch;

Do you prefer sans serif over serif?

You can change your font preferences in the "misc" section of your settings. ❤️