1

After I use reduce() to group the objects in an array by month-year:

let groupByMonth;
if (newlistTaskEvaluation) {
    groupDataByMonth = newlistTaskEvaluation.reduce((groups, item) => {
     groups[item.time] = [...groups[item.time] || [], item];
      return groups;
     }, {});
}

I have an array of event objects formatted by group month-year as follows:

groupByMonth = {
    '7-2020': [ //july
        {
            time: "7-2020",
            task: [
                { code: "p1", value: 123 },
                { code: "p2", value: 234 },
            ]
        },
        {
            time: "7-2020",
            task: [
                { code: "p1", value: 345 },
                { code: "p2", value: 456 },
            ]
        },
    ],
    '8-2020': [ //august
        {
            time: "8-2020",
            task: [
                { code: "p1", value: 567 },
                { code: "p2", value: 678 },
            ]
        },
        {
            time: "8-2020",
            task: [
                { code: "p1", value: 789 },
                { code: "p2", value: 999 },
            ]
        },
    ]
}

How to group object of Array by key 'code', time and total sum by value?

Expected result:

output = [
    {
        time: "7-2020", //total month 7-2020
        task: [
            { code: "p1", valueSum: 468 }, // 123 + 345
            { code: "p2", valueSum: 690 }, // 234 +456
        ] 
    },
    {
        time: "8-2020",
        task: [
            { code: "p1", valueSum: 1356 }, // 567 + 789
            { code: "p2", valueSum: 1677 }, // 999 +678
        ]
    }
]

Please help me.

3
  • 2
    please add your try. Commented Aug 7, 2020 at 7:03
  • @NinaScholz code here: let groupDataByMonth; if (newlistTaskEvaluation) { groupByMonth = newlistTaskEvaluation.reduce((groups, item) => { groups[item.time] = [...groups[item.time] || [], item]; return groups; }, {}); } Commented Aug 7, 2020 at 7:16
  • 1
    please add this to the question. Commented Aug 7, 2020 at 7:17

2 Answers 2

2

You could try something like this

const output = Object.entries(groupByMonth).map(([time, datapoints]) => {
  const codes = {}
  const allTasks = datapoints.flatMap(point => point.task)
  for (const { code, value } of allTasks) {
    codes[code] = (codes[code] || 0) + value
  }
  return {
    time,
    tasks: Object.entries(codes).map(([code, value]) => ({ code, value }))
  }
}

Though one downside is that the time complexity isn't perfect because of the structure of the data

Sign up to request clarification or add additional context in comments.

1 Comment

I tried quickly to use it and got the right result. Thank you <3
2
    const groupByMonth = {
  "7-2020": [
    //july
    {
      time: "7-2020",
      task: [
        { code: "p1", value: 123 },
        { code: "p2", value: 234 },
      ],
    },
    {
      time: "7-2020",
      task: [
        { code: "p1", value: 345 },
        { code: "p2", value: 456 },
      ],
    },
  ],
  "8-2020": [
    //august
    {
      time: "8-2020",
      task: [
        { code: "p1", value: 567 },
        { code: "p2", value: 678 },
      ],
    },
    {
      time: "8-2020",
      task: [
        { code: "p1", value: 789 },
        { code: "p2", value: 999 },
      ],
    },
  ],
};

const result = Object.keys(groupByMonth).reduce((arr, key)=>{
  const task = (groupByMonth[key]).reduce((acc, rec) => {
    return [...acc, rec.task]
  }, [])
    const newObj = {time: key, task}
    return [...arr, newObj]
}, [])

console.log(JSON.stringify(result, 2, 2))

You can get object's keys and when you iterate over them find out inner objects, then, in every object use another oner reduce to get tasks in that data-type what you need. for iterations i suddenly use reduce() method as a swiss-knife to working with arrays.

3 Comments

This will be faster .reduce((acc, rec) => { acc.push(rec.task); return acc; }, []). Spreading arrays and objects is recommended but you don't have to waste time on acc because he is only used inside reducer, and spreading the acc array is most costly than adding that one item to it.
thanks! it's my well-known problem - writing more code then conditions really need according task
@Paul Zaslavskij i want the output looks like this: output = [ { time: "7-2020", //total month 7-2020 task: [ { code: "p1", valueSum: 468 }, // 123 + 345 { code: "p2", valueSum: 690 }, // 234 +456 ] }, { time: "8-2020", task: [ { code: "p1", valueSum: 1356 }, // 567 + 789 { code: "p2", valueSum: 1677 }, // 999 +678 ] } ]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.