DEV Community

Cover image for Learn Javascript Reduce method with 10 examples
Ramiro - Ramgen
Ramiro - Ramgen

Posted on • Updated on • Originally published at ramagg.com

Learn Javascript Reduce method with 10 examples

The reduce method applies a function to every item of an array and accumulates the result iteratively from a starting point then returns a single value/object.

image

This starting value can be specified or if not reduce will use the first item in the array.

Most of these examples might not be the idea solution for the problem, but the idea is to illustrate how we can use reduce to solve them.

Alright let's start with.

Summation and Multiplication:

βˆ‘and∏ \sum and \prod

// Summation
[3, 5, 4, 3, 6, 2, 3, 4].reduce((a, i) => a + i);

// Without initial value
[3, 5, 4, 3, 6, 2, 3, 4].reduce((a, i) => a + i, 5 );

// For clarity the above code is the same as 
[3, 5, 4, 3, 6, 2, 3, 4].reduce(function(a, i){return (a + i)}, 0 );

// Multiplication
[3, 5, 4, 3, 6, 2, 3, 4].reduce((a, i) => a * i);
Enter fullscreen mode Exit fullscreen mode

In this example you can leave the initial value out, as it will grab the first item in the array, but you can also give it to have an offset or a bias pretty useful for that.

Find the maximum in an array:

[3, 5, 4, 3, 6, 2, 3, 4].reduce((a, i) => Math.max(a, i), -Infinity);
Enter fullscreen mode Exit fullscreen mode

Here in each iteration we return the max between the accumulator and the current item and in the end we have the max of the entire array.
Don't use this if you actually want to find the max in an array, you could use:

Math.max(...[3, 5, 4, 3, 6, 2, 3, 4]);
Enter fullscreen mode Exit fullscreen mode

Concatenating uneven arrays

let data = [
  ["The","red", "horse"],
  ["Plane","over","the","ocean"],
  ["Chocolate","ice","cream","is","awesome"], 
  ["this","is","a","long","sentence"]
]
let dataConcat = data.map(item=>item.reduce((a,i)=>`${a} ${i}`))

// Result
['The red horse', 
'Plane over the ocean', 
'Chocolate ice cream is awesome', 
'this is a long sentence']
Enter fullscreen mode Exit fullscreen mode

Pretty simple, here we also use map to go through each item in the array and we do a reduce with all the arrays, and we reduce the array into a single string.

Removing duplicates in an array:

let dupes = [1,2,3,'a','a','f',3,4,2,'d','d']
let withOutDupes = dupes.reduce((noDupes, curVal) => {
  if (noDupes.indexOf(curVal) === -1) { noDupes.push(curVal) }
  return noDupes
}, [])
Enter fullscreen mode Exit fullscreen mode

We check if the current value has index on the accumulator array if not is going to return -1 hence is not in the array and we can add it.
You can do this much better with a javascript set, since by default it stores only unique values, but either way i think it's a neat algorithm to think about.

Validating parenthesis

[..."(())()(()())"].reduce((a,i)=> i==='('?a+1:a-1,0);

//Long way with for loop
status=0
for i in string:
  if(i=="("):
    status=status+1
  elif(i==")"):
    status=status-1     
  if(status<0):
    return False
Enter fullscreen mode Exit fullscreen mode

This is a cool one that I adapted from a coding challenge that I did a while ago.
In the long way we can end the loop sooner, by checking if status is less than 0 in any point.
Here the condition is, if status is 0, the parenthesis are correct otherwise there is an imbalance.

Group by property

let obj = [
  {name: 'Alice', job: 'Data Analyst', country: 'AU'},
  {name: 'Bob', job: 'Pilot', country: 'US'},
  {name: 'Lewis', job: 'Pilot', country: 'US'},
  {name: 'Karen', job: 'Software Eng', country: 'CA'},
  {name: 'Jona', job: 'Painter', country: 'CA'},
  {name: 'Jeremy', job: 'Artist', country: 'SP'},
]
let ppl = obj.reduce((group, curP) => {
  let newkey = curP['country']
  if(!group[newkey]){
    group[newkey]=[]
  }
  group[newkey].push(curP)
  return group
}, [])
Enter fullscreen mode Exit fullscreen mode

Here we group the first array of objects by the country key, in each iteration, we check if the key exist if not we create an array, then we add the current person to that and we return the group array.
You can make a function with this to group the objects with an specified key.

Flattened an array of arrays

let flattened = [[3, 4, 5], [2, 5, 3], [4, 5, 6]].reduce(
  (singleArr, nextArray) => singleArr.concat(nextArray), [])
// results is [3, 4, 5, 2, 5, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

This is only 1 level deep but it you can adapt this with a recursive function, but i'm not that fan of making recursive things on javascript πŸ˜‚
An intended way of doing this is just to use the .flat method, it will do the same

[ [3, 4, 5],
  [2, 5, 3],
  [4, 5, 6]
].flat();
Enter fullscreen mode Exit fullscreen mode

Power only positive numbers

[-3, 4, 7, 2, 4].reduce((acc, cur) => {
  if (cur> 0) {
    let R = cur**2;
    acc.push(R);
  }
  return acc;
}, []);

// Result
[16, 49, 4, 144]
Enter fullscreen mode Exit fullscreen mode

This one is like doing a map and a filter at the same time, we filter the negative numbers and we rise the positive.

Reverse a string

const reverseStr = str=>[...str].reduce((a,v)=>v+a)
Enter fullscreen mode Exit fullscreen mode

This will work with any object not only with strings, also note that with this syntax we have the reduce in a function so we can call reverseStr("Hola") and it will give aloH πŸ˜‚

Binary to decimal

const bin2dec = str=>[...String(str)].reduce((acc,cur)=>+cur+acc*2,0)

// Long format for readability
const bin2dec = (str) => {
  return [...String(str)].reduce((acc,cur)=>{
    return +cur+acc*2
  },0)
}
Enter fullscreen mode Exit fullscreen mode

To Ilustrate this one lets see an example:
(10111)->1+(1+(1+(0+(1+0*2)*2)*2)*2)*2
This one is a little different to illustrate but think as if the first run is the one on the middle and it expands outwards from the center.

I'll appreciate if you give me a follow, I plan to do more content here, also if you have time check out my youtube channel ramgendeploy drop a sub if you like there πŸ˜„

And that's it I hope you now have a better understanding of reduce now choose the correct tool for the correct problem.

I hope one day you can use reduce in a cool way and feel good about yourself πŸ˜‚

Thanks to @jonrandy for these last 2

Discussion (32)

Collapse
lukeshiru profile image
LUKESHIRU

You can do pretty much anything with Array.prototype.reduce, but you should keep in mind that almost always there are more readable or performant solutions. Based on this, the first example is ok (generally Array.prototype.reduce is useful for sums), but for the rest:

  • Find the maximum in an array: You can just spread the array with Math.max.
Math.max(...[3, 5, 4, 3, 6, 2, 3, 4]);
Enter fullscreen mode Exit fullscreen mode
  • Removing duplicates in an array: You can just use Set:
const dupes = [1, 2, 3, "a", "a", "f", 3, 4, 2, "d", "d"];
const withoutDupes = [...new Set(dupes)];
Enter fullscreen mode Exit fullscreen mode
  • Extract properties in an array of objects returning an array: You already pointed out map is a better fit, being that you're turning the property values into arrays, you could just use Object.values:
[
    { name: "Alice", job: "Data Analyst", country: "AU" },
    { name: "Bob", job: "Pilot", country: "US" },
    { name: "Karen", job: "Software Eng", country: "CA" },
    { name: "Jeremy", job: "Artist", country: "SP" }
].map(Object.values);
Enter fullscreen mode Exit fullscreen mode
  • Flattened an array of arrays: You can just use Array.prototype.flat:
const flattened = [
    [3, 4, 5],
    [2, 5, 3],
    [4, 5, 6]
].flat();
Enter fullscreen mode Exit fullscreen mode

Cheers!

Collapse
ramgendeploy profile image
Ramiro - Ramgen Author • Edited on

Those are awesome suggestions, the post was more to have examples on how to use reduce than the most performant way of doing things πŸ˜…,
as reduce is widely used on react and it's really useful to know how the vanilla javascript method works,
but yea knowing the best way of doing things is important.
I appreciate the time you have put in the comment, Thanks πŸ˜„

Collapse
lukeshiru profile image
LUKESHIRU

Can you provide examples of the "wide use in React"? AFAIK the same applies for React: "Generally there are better solutions than reduce", similar to how generally there are better solutions than useEffect or useRef. I'm not saying you should never use reduce, I'm just saying you shouldn't default to it (using the same tool for every problem), because for the vast majority of scenarios there are better solutions.

Thread Thread
ramgendeploy profile image
Ramiro - Ramgen Author

For sure, I'm basicaly refering to the context api, it uses reduce as one of the main methods and it useful to know how .reduce works. Also if I'm not wrong useState uses useReducer at the backend but I can be mistaken, but anyways the useReducer hook can be used instead of useState when you have complex logic.

And you are right, you have to use the right tool for the right problem, I'm not arguing with that πŸ˜ƒ
Although, I'm not sure if I'm on the same page with "generally there is a better solution than useEffect and useRef", those are really useful hooks that in the most part will do a fine job at any problem.

Thread Thread
lukeshiru profile image
LUKESHIRU

Just to be clear: useReducer is not the same thing as Array.prototype.reduce, so that comparison wouldn't be valid. And when I said:

generally there are better solutions than useEffect or useRef.

What I mean is that generally, the problem can be solved with other hooks, so both useEffect and useRef are more like "last resources", so if those are the first solutions that come to mind, you might have to do a little more thinking.

Thread Thread
ramgendeploy profile image
Ramiro - Ramgen Author

Yes you are correct, those are not the same, but useReducer, has the same idea behind so it really useful to understand array.prototype.reduce to understand things like useReducer.
Well I guess I need to do more thinking then πŸ˜…

Thread Thread
fbolaji profile image
Francis.B

I understand both of your arguments and illustrate of how .reduce() works.

Collapse
fbolaji profile image
Francis.B

I rarely use Reduce in react as there more efficient methods to manipulate data as @lukeshiru mentioned.
I personal use all eas6 methods in React most of the time:
.filter()
.map()
new Set()
.find()
.findIndex()
.includes()
Object.is()
[].entries()
[].keys()
[].values()
.sort()
and untility library such as lodash
then occasionally .reduce() .some()

Thread Thread
ramgendeploy profile image
Ramiro - Ramgen Author

I also rarely use reduce in react, but I was working with the context api the other day and it really was useful to know how the reduce method worked to understand the api (at least the part where there is reduce like syntax), but yea with array manipulation reduce is at the bottom of the list πŸ˜…

Collapse
pengeszikra profile image
Peter Vivo

reducer in React means total different things, than array reduce function ... which is really useful tool as you described. reducer in React means pure function which modify state by action payload.

Thread Thread
ramgendeploy profile image
Ramiro - Ramgen Author

Yes you are correct, they are not the same, Thank for the comment.

Collapse
lionelrowe profile image
lionel-rowe

There's a great HTTP 203 video about that here: Is reduce() bad? - HTTP 203

The title is maybe a little clickbait-ey, but they do make a pretty good reasoned argument for "yes... mostly" and give some great examples for how to rewrite such code in more readable ways.

Collapse
lukeshiru profile image
LUKESHIRU • Edited on

Indeed! Jake started the discussion in Twitter, I made a post about it as well ... but the TL;DR is "you should use the tool that makes the most sense for the particular task", Array.prototype.reduce is extremely versatile, but generally there are better alternatives to achieve the same tasks that are more readable and have better performance :)

Collapse
jonrandy profile image
Jon Randy

On your summing example, you're providing the initial value of 0 which isn't necessary - and actually makes it slightly less efficient. If you omit the initial value, the first value of the array will be used instead - reduce will then proceed from the second item in the list

Collapse
lionelrowe profile image
lionel-rowe • Edited on

Omitting the initial value is an antipattern that makes your code much harder to reason about. Let's say you want to concatenate digits into a string (deliberately oversimplified example, you'd just use join for this in real life):

const zeroDigits = []
const oneDigit   = [1]
const twoDigits  = [1, 2]

zeroDigits.reduce((a, c) => String(a) + String(c)) // throws TypeError
oneDigit  .reduce((a, c) => String(a) + String(c)) // number 1
twoDigits .reduce((a, c) => String(a) + String(c)) // string '12'
Enter fullscreen mode Exit fullscreen mode
Collapse
jonrandy profile image
Jon Randy • Edited on

Being 'hard to reason about' is purely subjective, and down to the individual. It's a perfectly valid language feature that has a valid use.

Thread Thread
lionelrowe profile image
lionel-rowe • Edited on

You can't possibly be arguing that saving the 2 or 3 minified bytes from writing ,0 or ,'' or the amount of processing power required to add zero to something is somehow worth the likelihood of your code taking a single input type and outputting two unrelated types or throwing an error?

I notice your reverseStr function from your other comment suffers from this problem β€” did you realize that when you wrote it?

const reverseStr = str => [...str].reduce((a, v) => v + a)

reverseStr('') // throws TypeError
Enter fullscreen mode Exit fullscreen mode
Thread Thread
jonrandy profile image
Jon Randy

Yes

Collapse
ramgendeploy profile image
Ramiro - Ramgen Author

Right! I forgot to mention that, nice catch πŸ˜„

Collapse
jonrandy profile image
Jon Randy

Might want to re-check the summation and multiplication section - still some issues there

Collapse
jonrandy profile image
Jon Randy • Edited on

Reverse a string:

const reverseStr = str=>[...str].reduce((a,v)=>v+a)
Enter fullscreen mode Exit fullscreen mode

Convert a binary number in a string to a decimal:

const bin2dec = str=>[...str].reduce((a,v)=>+v+a*2,0)
Enter fullscreen mode Exit fullscreen mode
Collapse
ramgendeploy profile image
Ramiro - Ramgen Author

Oh nice adding these examples to the post, Thanks!

Collapse
suchitra_13 profile image
Suchitra

Nice article!!
Btw I wanna ask you that which markdown format you used for the code color them cuz whenever I used to code it simply displayed in write colored text!
Please specify:)
though it is out of the topic question:P

Collapse
ramgendeploy profile image
Ramiro - Ramgen Author • Edited on

Thanks! to have the code with the right color format you do
´´´javascript <- language name here
let data=[]
...
´´´
Here change the commas for the right ones, this is to not have this comment formatted, the right ones are these `

Collapse
suchitra_13 profile image
Suchitra

Thanks I will try!

Collapse
wedemboyzxs profile image
link

I love the reduce method. I use it for everything. I would brush my teeth with it if I could. If you ever map filter map find anything, do everyone a solid and just use reduce.
loveland co roofing company

Collapse
shriyastout profile image
ShriyaStout

These are the best and most effective suggestions shared by you here , thanks for your help. dua to make someone talk to you again

Collapse
janiceperry profile image
JanicePerry

The reduce() method executes a user-supplied β€œreducer” callback function on each ... This is shown in the following interactive example. white magic for love

Collapse
wegissilveira profile image
wegissilveira

Thank you, man.

Have a better understanding of Reduce has been on my todo list for a while. You really helped me with this article.

Collapse
ramgendeploy profile image
Ramiro - Ramgen Author

Thanks! Glad you like it 😁

Collapse
qq449245884 profile image
qq449245884

Dear Ramiro,may I translate your article into Chinese?I would like to share it with more developers in China. I will give the original author and original source.

Collapse
ramgendeploy profile image
Ramiro - Ramgen Author

Sure, that'll be awesome 😁