Search code examples
javascriptarraysjsonobject

Merge array of objects based on overall key of object


I have this array of objects

var worksSummaryDetailsArr = [
  {
    year: 2020,
    worksSummaryDetailsObj: [ [Object], [Object], [Object], [Object] ]
  },
  {
    year: 2021,
    worksSummaryDetailsObj: [ [Object], [Object], [Object], [Object] ]
  },
  {
    year: 2022,
    worksSummaryDetailsObj: [ [Object], [Object], [Object], [Object] ]
  },
  {
    year: 2021,
    worksSummaryDetailsObj: [ [Object], [Object], [Object], [Object] ]
  },
  {
    year: 2022,
    worksSummaryDetailsObj: [ [Object], [Object], [Object], [Object] ]
  }
]

I want to merge it into


  {
    year: 2020,
    worksSummaryDetailsObj: [ [Object], [Object], [Object], [Object] ]
  },
  {
    year: 2021,
    worksSummaryDetailsObj: [ [Object], [Object], [Object], [Object],[Object], [Object], [Object], [Object] ]
  },
  {
    year: 2022,
    worksSummaryDetailsObj: [ [Object], [Object], [Object], [Object],[Object], [Object], [Object], [Object] ]
  },

I have tried using the set function and mapping with the same year, and the output was the same years were merged correctly but the worksSummaryDetailsObj contains wrong data

here is my code


const r = [...new Set(worksSummaryDetailsArr.map((i) => i.year))].map((i) => ({
      year: i,
      worksSummaryDetailsObj: [...new Set(worksSummaryDetailsArr.filter(({ year: c }) => c === i))],
}));

console.log(r);

Solution

  • a simple reduce and array merge could achieve what you want

    Object.values(
      worksSummaryDetailsArr.reduce((acc, arr) => {
        if (!acc[arr.year]) {
          acc[arr.year] = arr;
        } else {
          acc[arr.year] = {
            ...acc[arr.year],
            worksSummaryDetailsObj: [
              ...acc[arr.year].worksSummaryDetailsObj,
              ...arr.worksSummaryDetailsObj,
            ],
          };
        }
        return acc;
      }, {})
    );