'How to sort array of objects by dates and make new arrays which will contain all objects with same date [closed]

I have a very specific problem in Javascript. I have array of objects, and each object contains some date.

const array = [
{name: 'first', date: '2020-05-06'},
{name: 'second', date: '2020-04-07'},
{name: 'third', date: '2020-05-06'},
{name: 'fourth', date: '2020-04-07'},
{name: 'fifth', date: '2020-04-09'}
]

For each unique date in array I need to make an object with key of that unique date and put all the elements of array in that object:

[{name: 'first', date: '2020-05-06'}, {name: 'third', date: '2020-05-06'}]
[{name: 'second', date: '2020-04-07'} {name: 'fourth', date: '2020-04-07'}]
[{name: 'fifth', date: '2020-04-09'}]

Any help would mean a lot. Thank you all!



Solution 1:[1]

you can use .reduce(), i leave you this example:

let foo = [
{name: 'first', date: '2020-05-06'},
{name: 'second', date: '2020-04-07'},
{name: 'third', date: '2020-05-06'},
{name: 'fourth', date: '2020-04-07'},
{name: 'fifth', date: '2020-04-09'}
];
let boo = foo.reduce((acc, elem) => {
  (acc[elem.date] ??= []).push(elem);
  // since OP said they have eslint issues with ??=
  // following may be used instead of the above line
  // acc[elem.date] = (acc[elem.date] || []).concat([elem])
  return acc;
}, {});

console.log('output: ', boo);

result:

{
  '2020-05-06': [
    { name: 'first', date: '2020-05-06' },
    { name: 'third', date: '2020-05-06' }
  ],
  '2020-04-07': [
    { name: 'second', date: '2020-04-07' },
    { name: 'fourth', date: '2020-04-07' }
  ],
  '2020-04-09': [ { name: 'fifth', date: '2020-04-09' } ]
}

Solution 2:[2]

Almost any array specific task which somehow involves grouping will be solved most convenient by a reduce based approach.

Regardless of the OP's final data structure one would start with the aggregation of an object which is going to feature date specific entries where each key represents a unique date value and each value is an array of items of such same dates.

In order to get an array of such grouped arrays one would pass the reduced object to Object.values.

One of cause could always enforce a date specific item precedence by applying a sort task first.

function groupAndCollectSameDateItem(result, item) {
  // access item date.
  const { date } = item;
  
  // access or create `date` specific
  // group array and collect item.
  (result[date] ??= []).push(item);

  return result;
}

const dateItems = [
  { name: 'first', date: '2020-05-06' },
  { name: 'second', date: '2020-04-07' },
  { name: 'third', date: '2020-05-06' },
  { name: 'fourth', date: '2020-04-07' },
  { name: 'fifth', date: '2020-04-09' },
];

console.log(
  'index/map of arrays of same date items grouped by a date key ...',
  dateItems
    .reduce(groupAndCollectSameDateItem, {})
);
console.log(
  'sort items in ascending date order before creating the index ...',
  dateItems
    .sort((a, b) =>
      new Date(a.date).getTime() - new Date(b.date).getTime()
    )
    .reduce(groupAndCollectSameDateItem, {})
);
console.log(
  'array of arrays of same date items in ascending date order ...',
  Object
    .values(
      dateItems
        .sort((a, b) =>
          new Date(a.date).getTime() - new Date(b.date).getTime()
        )
        .reduce(groupAndCollectSameDateItem, {})
  )
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

Edit

"... Our project eslint does not allow the ??= symbol. – Marin"

The alternative implementation for not using the Logical nullish assignment operator might look similar to the next example code ...

function groupAndCollectSameDateItem(result, item) {
  // access item date.
  const { date } = item;
  
  // access or create `date` specific
  // group array and collect item.
  let groupList = result[date];
  if (!groupList) {
    groupList = result[date] = [];
  }
  groupList.push(item)

  return result;
}

const dateItems = [
  { name: 'first', date: '2020-05-06' },
  { name: 'second', date: '2020-04-07' },
  { name: 'third', date: '2020-05-06' },
  { name: 'fourth', date: '2020-04-07' },
  { name: 'fifth', date: '2020-04-09' },
];

console.log(
  'index/map of arrays of same date items grouped by a date key ...',
  dateItems
    .reduce(groupAndCollectSameDateItem, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

Solution 3:[3]

What you need is a groupBy implementation. Lodash library has it https://lodash.com/docs/#groupBy

Example: https://stackblitz.com/edit/js-twywom?file=index.js

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jsN00b
Solution 2
Solution 3