如何按日期对对象数组进行排序并创建包含具有相同日期的所有对象的新数组

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

我在 Javascript 中有一个非常具体的问题。我有对象数组,每个对象都包含一些日期。

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'}
]

对于数组中的每个唯一日期,我需要使用该唯一日期的键创建一个对象,并将数组的所有元素放入该对象中:

[{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'}]

任何帮助都意义重大。谢谢大家!

您需要的是 groupBy 实现。 Lodash 库有它 https://lodash.com/docs/#groupBy

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

几乎所有以某种方式涉及分组的特定于数组的任务都可以通过基于 reduce 的方法最方便地解决。

无论 OP 的最终数据结构如何,我们都将从聚合一个对象开始,该对象将具有 date 个特定条目,其中每个键代表一个唯一的日期值,每个值都是一组项目同样的日期。

为了获得一组这样的分组数组,可以将减少的对象传递给 Object.values

一个原因总是可以通过首先应用 sort 任务来强制执行特定于日期的项目优先级。

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; }

编辑

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

不使用 Logical nullish assignment operator 的替代实现可能类似于下一个示例代码...

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; }

你可以使用.reduce(),我留给你这个例子:

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);

结果:

{
  '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' } ]
}