tharindu
tharindu

Reputation: 523

Grouping values of an array by multiple keys using reduce() in javascript

I have the following array

var array = [
   {id:"1",subject:"CE1",mark:"20"},{id:"1",subject:"CE2",mark:"30"},
   {id:"2",subject:"CE1",mark:"40"},{id:"3",subject:"CE1",mark:"20"},
   {id:"3",subject:"CE2",mark:"20"},{id:"1",subject:"CE1",mark:"40"},
   {id:"1",subject:"CE2",mark:"30"},{id:"2",subject:"CE1",mark:"20"},
   {id:"3",subject:"CE1",mark:"10"},{id:"3",subject:"CE2",mark:"10"}
]

and I want the following array

var resultArray = [
    {id:"1",subject:"CE1",mark:"60"},
    {id:"1",subject:"CE2",mark:"60"},
    {id:"2",subject:"CE1",mark:"40"},
    {id:"3",subject:"CE1",mark:"30"},
    {id:"3",subject:"CE2",mark:"30"}
]

I have the following code which group the array by id only.

var totalArray = Object.values(array .reduce((a, {id, subject, mark}) => { 
    let totMark= mark;
    if(a.hasOwnProperty(id)) {
        a[id].mark+= totMark;
    } else {
        a[id] = {
            id:id,
            subject:subject,
            mark:totMark,

        }
    }
    return a;
}, {}));

How can I group my array by two properties using javascript?

Upvotes: 1

Views: 1842

Answers (2)

Elisheva
Elisheva

Reputation: 33

@adiga's answer will always add the first matching key twice. The first time a key comes up, we don't want to add it to itself!

This line

acc[key] = acc[key] || { id, subject, mark };

needs to be

acc[key] = acc[key] || { id, subject, mark: 0 };

Final snippet:

var array = [
   {id:"1",subject:"CE1",mark:"20"},{id:"1",subject:"CE2",mark:"30"},
   {id:"2",subject:"CE1",mark:"40"},{id:"3",subject:"CE1",mark:"20"},
   {id:"3",subject:"CE2",mark:"20"},{id:"1",subject:"CE1",mark:"40"},
   {id:"1",subject:"CE2",mark:"30"},{id:"2",subject:"CE1",mark:"20"},
   {id:"3",subject:"CE1",mark:"10"},{id:"3",subject:"CE2",mark:"10"}
]

var totalArray = Object.values(array.reduce((acc, { id, subject, mark }) => {
  mark = +mark; // convert to number
  const key = id + '_' + subject; // unique combination of id and subject
  acc[key] = acc[key] || { id, subject, mark: 0 };
  acc[key].mark += mark;
  return acc;
}, {}));

console.log(totalArray)

Upvotes: 2

adiga
adiga

Reputation: 35222

You need to follow a similar approach. Instead of adding id as a key to the accumulator, you can create a new key which is a combination of the 2 keys you want to group with.

var array = [
   {id:"1",subject:"CE1",mark:"20"},{id:"1",subject:"CE2",mark:"30"},
   {id:"2",subject:"CE1",mark:"40"},{id:"3",subject:"CE1",mark:"20"},
   {id:"3",subject:"CE2",mark:"20"},{id:"1",subject:"CE1",mark:"40"},
   {id:"1",subject:"CE2",mark:"30"},{id:"2",subject:"CE1",mark:"20"},
   {id:"3",subject:"CE1",mark:"10"},{id:"3",subject:"CE2",mark:"10"}
]

var totalArray = Object.values(array.reduce((acc, { id, subject, mark }) => {
  mark = +mark; // convert to number
  const key = id + '_' + subject; // unique combination of id and subject
  acc[key] = acc[key] || { id, subject, mark };
  acc[key].mark += mark;
  return acc;
}, {}));

console.log(totalArray)

Upvotes: 1

Related Questions