как отсортировать объекты по массивам

есть массив объктов:

[

 {category:1, product: 1},

 {category:1, product: 2},

 {category:1, product: 3},

 {category:2, product: 4},

 {category:2, product: 5},

 {category:3, product: 6},

 {category:4, product: 7}

]

нужно отсортировать массив по котегориям так чтобы на выходе был:

[
  [
    {category:1, product: 1},

    {category:1, product: 2},

    {category:1, product: 3}
  ],

  [
   {category:2, product: 4},

   {category:2, product: 5},
  ],
  [
   {category:3, product: 6},
  ],
  [
   {category:4, product: 7}
  ]
] 

сортировать нужно по категориям и массивы должны быть динамическими. никак не пойму как решить, попытался отсортировать по возростанию числа категорий, потом найти первый и последний индекс определённых категорий и при помощ slice() отрезать нужные объекты, но такой способ думаю не оптимальный


Ответы (2 шт):

Автор решения: vsemozhebuty

Можно использовать временную промежуточную структуру, чтобы сгруппировать объекты по нужному ключу, а потом преобразовать её в нужный формат. Так мы расходуем больше памяти, но немного экономим на времени, потому что не нужно постоянно искать нужное место для текущего элемента, обыскивая строящуюся окончательную структуру.

const data1 = [
  {category:1, product: 1},
  {category:1, product: 2},
  {category:1, product: 3},
  {category:2, product: 4},
  {category:2, product: 5},
  {category:3, product: 6},
  {category:4, product: 7},
];

const temp = data1.reduce(
  (acc, object) => {
    if (!acc[object.category]) acc[object.category] = [];
    acc[object.category].push(object);
    return acc;
  },
  {},
);

const data2 = Object.values(temp);

console.log(data2);

Можно ещё использовать ключ как индекс массива и потом вычистить дыры. Правда из-за чистки дыр мы по сути тоже используем временную структуру и на это тоже уйдёт память и время)

const data1 = [
  {category:1, product: 1},
  {category:1, product: 2},
  {category:1, product: 3},
  {category:2, product: 4},
  {category:2, product: 5},
  {category:3, product: 6},
  {category:4, product: 7},
];

const data2 = data1.reduce(
  (acc, object) => {
    if (!acc[object.category]) acc[object.category] = [];
    acc[object.category].push(object);
    return acc;
  },
  [],
).filter(Boolean);

console.log(data2);

→ Ссылка
Автор решения: entithat

А можно сразу вставлять элементы в нужные места.

const arr = [
 {category:1, product: 1},
 {category:1, product: 2},
 {category:1, product: 3},
 {category:2, product: 4},
 {category:2, product: 5},
 {category:3, product: 6},
 {category:4, product: 7}
];

console.log(arr.reduce((acc, cur) => {
  const idx = acc.findIndex(e => e[0].category === cur.category);
  idx === -1 ? acc.push([cur]) : acc[idx].push(cur);
  return acc;
}, []));

→ Ссылка