How to group an array of objects and mapping it to a different structure?

It’s actually about mapping an array of objects and grouping it. Is there any way to convert this array the javascript way without lodash

let fruits = [
  {
    id: 1,
    expired_date: "2021-11-30",
    name: "mango"
  },
  {
    id: 2,
    expired_date: "2021-11-20",
    name: "kiwi"
  },
  {
    id: 3,
    expired_date: "2021-11-20",
    name: "orange"
  },
  {
    id: 4,
    expired_date: "2021-11-10",
    name: "banana"
  },
  {
    id: 5,
    expired_date: "2021-11-10",
    name: "apple"
  }
]

grouped to something like this? (grouped by a key in the object, wrapped in an object with 2 keys, one contains the category and the other contains the objects relevant to the group)

let fruits = [
  {
    expired_date: "2021-11-30",
    rows: [
      {
        id: 1,
        expired_date: "2021-11-30",
        name: "mango"
      }
    ]
  },
  {
    expired_date: "2021-11-20",
    rows: [
      {
        id: 2,
        expired_date: "2021-11-20",
        name: "kiwi"
      },
      {
        id: 3,
        expired_date: "2021-11-20",
        name: "orange"
      }
    ]
  },
  {
    expired_date: "2021-11-10",
    rows: [
      {
        id: 4,
        expired_date: "2021-11-10",
        name: "banana"
      },
      {
        id: 5,
        expired_date: "2021-11-10",
        name: "apple"
      }
    ]
  }
]

I’ve read this question but it’s not quite the same as expected

Answer

Array.reduce should work

const fruits = [  {    id: 1,    expired_date: "2021-11-30",    name: "mango"  },  {    id: 2,    expired_date: "2021-11-20",    name: "kiwi"  },  {    id: 3,    expired_date: "2021-11-20",    name: "orange"  },  {    id: 4,    expired_date: "2021-11-10",    name: "banana"  },  {    id: 5,    expired_date: "2021-11-10",    name: "apple"  }];

const result = Object.values(fruits.reduce((acc, item) => {
    (acc[item.expired_date]??={expired_date: item.expired_date, rows: []}).rows.push(item);
    return acc;
}, {}));

console.log(result);

Revised without ??= assignment, it’s not supported in IE.

const result = Object.values(fruits.reduce((acc, item) => {
  if (acc[item.expired_date]) {
    acc[item.expired_date].rows.push(item);
  } else {
    acc[item.expired_date] = {expired_date: item.expired_date, rows: [item]};
  }
  return acc;
}, {}));