Home > Net >  Combine same year items to one object
Combine same year items to one object

Time:09-22

I have an array of objects that look like this:

[
  {
    makeYear: 2019,
    company: 'Mazda',
    fleet: '900'
  },
  {
    makeYear: 2019,
    company: 'Mercedes',
    fleet: '500'
  },
  {
    makeYear: 2020,
    company: 'Honda',
    fleet: '390'
  },
  .....
]

I am trying to merge all the properties for a specific makeYear into one object that should look like this

[
  {
    makeYear: 2019,
    Mazda: 900,
    Mercedes: 500,
    //other companies present for the year
  },
  {
    makeYear: 2020,
    Honda: 390,
    //other companies present for the year
  },
  
];

I have tried it doing this way, but no luck.

const mergeObjs = input.reduce((res, item) => {
  if (!item.makeYear) return res;
  res[item.makeYear] = item;
  return res;
}, {});

const merged = input.filter(item => item.makeYear).map(item => {
  return {...item, ...(mergeObjs[item.makeYear] || {})}
});

Any idea how I can achieve this? TIA

CodePudding user response:

You can use reduce to group with makeYear as a key.

const data = [
  {
    makeYear: 2019,
    company: 'Mazda',
    fleet: '900'
  },
  {
    makeYear: 2019,
    company: 'Mercedes',
    fleet: '500'
  },
  {
    makeYear: 2020,
    company: 'Honda',
    fleet: '390'
  },
]


const result = data.reduce((acc, {makeYear, company, fleet}) => {
  let item = acc.find(i => i.makeYear === makeYear);
  if (item) {
    item[company] = fleet;
  } else {
    acc.push({
      makeYear,
      [company]: fleet,
    })
  }
  return acc
}, [])

console.log(result)

CodePudding user response:

You can use reduce() to collect values for each year. Then use entries() and map() to get your desired structure.

This implementation uses a Map, but you can also use a plain JavaScript object.

const input = [
  {
    makeYear: 2019,
    company: "Mazda",
    fleet: "900",
  },
  {
    makeYear: 2019,
    company: "Mercedes",
    fleet: "500",
  },
  {
    makeYear: 2020,
    company: "Honda",
    fleet: "390",
  },
];

const carsByYearAndMake = input.reduce((carsByYear, carsByMake) => {
  if (carsByYear.has(carsByMake.makeYear)) {
    const carsForYear = carsByYear.get(carsByMake.makeYear);
    carsForYear[carsByMake.company] = carsByMake.fleet;
  } else {
    carsByYear.set(carsByMake.makeYear, {
      [carsByMake.company]: carsByMake.fleet,
    });
  }
  return carsByYear;
}, new Map());

const output = [...carsByYearAndMake.entries()].map(
  ([year, fleetCountByMake]) => ({ year: year, ...fleetCountByMake })
);
console.log(JSON.stringify(output, null, 4));
/* StackOverflow snippet: console should overlap rendered HTML area */
.as-console-wrapper { max-height: 100% !important; top: 0; }

  • Related