Search code examples
javascriptjsonstatisticsaggregate

How to aggregate JSON data as expected?


I have response text from API as below, I want aggregate them to new format response. But it is quite difficult, please help me (using JavaScript)

Response from API:

[
  {
    sumTime: "2024-04-25 12:00:00",
    equipParaName: "P1",
    sumValue: 5
  },
  {
    sumTime: "2024-04-25 05:00:00",
    equipParaName: "P2",
    sumValue: 10,
  },
  {
    sumTime: "2024-04-25 09:00:00",
    equipParaName: "P1",
    sumValue: 8
  },
  {
    sumTime: "2024-04-25 08:00:00",
    equipParaName: "P2",
    sumValue: 3,
  },
  {
    sumTime: "2024-04-25 08:00:00",
    equipParaName: "P3",
    sumValue: 12,
  }
]

Conditions:

  • With same sumTime, the equipParaName can not be duplicated

  • If have 3 unique equipParaName, the expecting result has maximum 3 attributes belongs to them in one object

  • Same equipParaName in result list must order by sumTime ASC

    equipParaName: P1, sumTime: 2024-04-25 12:00:00, sumValue: 5
    equipParaName: P1, sumTime: 2024-04-25 09:00:00, sumValue: 8
    ==> The sumTime 2024-04-25 09:00:00 should be added to 1st object and sumTime: 2024-04-25 12:00:00 added to 2nd object in result list
    

Expect:

[
  {
    index: 1,
    P1: 8,
    P1_sumTime: "2024-04-25 09:00:00",
    P2: 10,
    P2_sumTime: "2024-04-25 05:00:00",
    P3: 12,
    P3_sumTime: "2024-04-25 07:00:00"
  },
  {
    index: 2,
    P1: 5,
    P1_sumTime: "2024-04-25 12:00:00",
    P2: 3,
    P2_sumTime: "2024-04-25 08:00:00"
  }
]

Solution

    1. group items by equipParaName and sort by sumTime
    2. collect items into the final group objects so there's only unique equipParaName in an object.

    const input=[{sumTime:"2024-04-25 12:00:00",equipParaName:"P1",sumValue:5},{sumTime:"2024-04-25 05:00:00",equipParaName:"P2",sumValue:10},{sumTime:"2024-04-25 09:00:00",equipParaName:"P1",sumValue:8},{sumTime:"2024-04-25 08:00:00",equipParaName:"P2",sumValue:3},{sumTime:"2024-04-25 08:00:00",equipParaName:"P3",sumValue:12}];
    
    const ps = input.reduce((r, item) => ((r[item.equipParaName] ??= []).push(item), r), {});
    const result = Array.from({length: Math.max(...Object.values(ps).map(arr => arr.length))}, (_, i) => ({index:i+1}));
    Object.keys(ps).sort().forEach(key => 
       ps[key].sort((a,b) => (a = a.sumTime, b = b.sumTime, a > b ? 1 : a < b ? -1 : 0))
        .forEach(({sumTime, sumValue}, i) => (result[i][key] = sumValue, result[i][key + '_sumTime'] = sumTime))
    );
    
    console.log(result);
    .as-console-wrapper{
    max-height:100% !important;
    }