如何使用reduce返回以数组作为值的映射对象?



我有一个不同的对象数组。有些具有相同的date值。我想将具有相同date的那些分组在一起并返回一个映射对象,其中每个date都是键,其值是具有相同日期的对象数组。这是数组:

const arr = [
{
date: '2/2/20',
name: 'joe',
age: 22
},
{
date: '3/3/20',
name: 'john',
age: 67
},
{
date: '2/2/20',
name: 'chuck',
age: 34
},
{
date: '3/3/20',
name: 'bob',
age: 28
},
{
date: '4/4/20',
name: 'bill',
age: 51
}
]

我知道这样的事情可以用map().filter()来完成,但这不是我想要的,而且我正在尝试用reduce()来节省资源。

到目前为止,我有:

arr.reduce((acc, person) => {
acc[person.date] = [ person ];
return acc;
}, {});

这仅返回最后一个匹配项,而不是所有匹配项:

{
'2/2/20': [ { date: '2/2/20', name: 'chuck', age: 34 } ],
'3/3/20': [ { date: '3/3/20', name: 'bob', age: 28 } ],
'4/4/20': [ { date: '4/4/20', name: 'bill', age: 51 } ]
}

我已经尝试了此解决方案的其他方面,但似乎无法正确处理。我也知道如何获取返回匹配数计数的映射对象,但这仍然不是我的解决方案:

arr.reduce((acc, person) => {
acc[person.date] = acc[person.date] + 1 || 1
return acc
}, {})

这将返回:

{ '2/2/20': 2, '3/3/20': 2, '4/4/20': 1 }

那么如何使用reduce()来获取包含所有匹配项的对象呢?

如果acc[person.date]不存在,则初始化为空数组,并且无论如何push

arr.reduce((acc, person) => {
acc[person.date] = (acc[person.date] || []);
acc[person.date].push(person);
return acc;
}, {});

解构单线/扩展方法:

arr.reduce((acc, { date, ...o }) => ({ ...acc, [date]: [...(acc[date] || []), { date, ...o }), {});

Jack Bashford的答案似乎是你要找的。我只想补充一点,这是一个非常常见的操作,通常称为groupBy.这在大多数功能帮助程序库(例如 Lodash(中实现。您也可以使用以下方法自行实现它:

const groupBy = (cb, arr) =>
arr.reduce((grouped, el) => {
const key = cb(el)
return {
...grouped,
[key]: [...grouped[key] || [], el]
}
}, {})

(请注意,上面的实现只是一个示例,不应被视为高性能实现。请参阅 Lodash 组通过实现。

然后对于您的用例:

groupBy(el => el.date, arr)

如果您打算执行类似的操作,这将很有帮助。

最新更新