Search code examples
javascriptarraysmapreducejavascript-objectsreduce

How to find the sum of a specific key in array of objects


I have an array of objects of the following structure:

[
 {
     _id: 60b18e0a7ba49519c1ee63b4,
     course: 'sfsdf',
     earnings: 100,
     creator: '607497d5f4bcc83fa1f3cedf',
     month: 1,
     year: 2019
   },
   {
     _id: 60b18e1a7ba49519c1ee63b5,
     course: 'sfsdf',
     earnings: 200,
     creator: '607497d5f4bcc83fa1f3cedf',
     month: 2,
     year: 2019
   },
   {
     _id: 60b18e227ba49519c1ee63b6,
     course: 'sfsdf',
     earnings: 300,
     creator: '607497d5f4bcc83fa1f3cedf',
     month: 3,
     year: 2019
   },
   {
     _id: 60b18e297ba49519c1ee63b7,
     course: 'sfsdf',
     earnings: 400,
     creator: '607497d5f4bcc83fa1f3cedf',
     month: 4,
     year: 2019
   },
   {
     _id: 60b18b907ba49519c1ee63a5,
     course: 'html-css',
     earnings: 1000,
     creator: '607497d5f4bcc83fa1f3cedf',
     month: 3,
     year: 2021
   },
   {
     _id: 60b18c457ba49519c1ee63a9,
     course: 'html-css',
     earnings: 500,
     creator: '607497d5f4bcc83fa1f3cedf',
     month: 2,
     year: 2020
   }
]

I want to manipulate the above array in a way so that the result looks like:

[
    { label: 2019, earnings: 1000 },
    { label: 2021, earnings: 1000 },
    { label: 2020, earnings: 500 },
]

where label is the unique year and earnings is the sum of all earnings for that year.

Question Explanation:

  1. there are 4 objects for the year 2019 with each year's earnings as 100, 200, 300, 400 respectively, this totals to 1000 (100 + 200 + 300 + 400) and hence the result array has { label: 2019, earnings: 1000 }

  2. there is 1 object for the year 2021 with earnings of 1000, therefore total earning is 1000 and hence the result array has { label: 2021, earnings: 1000 }

and so on similarly for the year 2020 also.


Solution

  • const result = arr.reduce((acc, obj) => {
        const idx = acc.findIndex(o => o.label === obj.year);
        if (idx !== -1) acc[idx].earnings += obj.earnings;
        else acc.push({ label: obj.year, earnings: obj.earnings });
        return acc;
    }, [])
    
    console.log(result)