如何按相同id、startDate和endDate分组JavaScript对象数组?
分组对象数组:按id、startDate和endDate完全匹配分组
需求:将对象数组中id、startDate、endDate三者完全相同的对象分组。规则:仅id相同但日期不同不分组;仅日期相同但id不同也不分组。
我尝试用forEach实现但未成功,代码如下:
const newDates: any[] = []; response.forEach((elem, index) => { if(newDates.length === 0) newDates.push([elem]) if(newDates.length > 0) { if( newDates[index][0].startDate === elem.startDate && newDates[index][0].endDate === elem.endDate && newDates[index][0].id === elem.id ) { newDates[index].push(elem) } else { newDates.push([elem]) } } })
示例输入
const response = [ { name: 'John', id: 1, startDate:'2022-10-31T00:00:00', endDate: '2022-12-01T00:00:00' }, { name: 'Alisha', id: 1, startDate:'2022-10-31T00:00:00', endDate: '2022-12-01T00:00:00' }, { name: 'Andrew', id: 4, startDate:'2022-10-05T00:00:00', endDate: '2022-11-01T00:00:00' }, { name: 'James', id: 4, startDate:'2022-10-05T00:00:00', endDate: '2022-11-01T00:00:00' }, { name: 'Kamilla', id: 4, startDate:'2022-11-14T00:00:00', endDate: '2022-11-18T00:00:00' }, { name: 'Oliver', id: 4, startDate:'2022-11-13T00:00:00', endDate: '2022-11-18T00:00:00' } ]
期望输出
const result = [ [ { name: 'John', id: 1, startDate:'2022-10-31T00:00:00', endDate: '2022-12-01T00:00:00' }, { name: 'Alisha', id: 1, startDate:'2022-10-31T00:00:00', endDate: '2022-12-01T00:00:00' }, ], [ { name: 'Andrew', id: 4, startDate:'2022-10-05T00:00:00', endDate: '2022-11-01T00:00:00' }, { name: 'James', id: 4, startDate:'2022-10-05T00:00:00', endDate: '2022-11-01T00:00:00' }, ], [ { name: 'Kamilla', id: 4, startDate:'2022-11-14T00:00:00', endDate: '2022-11-18T00:00:00' } ], [ { name: 'Oliver', id: 4, startDate:'2022-11-13T00:00:00', endDate: '2022-11-18T00:00:00' } ] ]
问题分析
原代码的核心错误是用response的索引index去匹配newDates的元素,逻辑完全不成立:
newDates的长度和response不同步,当index >= newDates.length时会直接报错- 仅和当前索引对应的组比较,不会检查所有已存在的组,导致符合条件的对象无法进入正确的组
正确实现(用reduce)
用reduce构建一个以id-startDate-endDate为键的对象,将相同键的对象归到同一数组,最后提取所有值即可得到分组结果:
const result = response.reduce((acc, elem) => { // 生成唯一分组键:组合id、startDate、endDate const key = `${elem.id}-${elem.startDate}-${elem.endDate}`; // 如果键不存在,初始化空数组 if (!acc[key]) { acc[key] = []; } // 将当前对象加入对应组 acc[key].push(elem); return acc; }, {} as Record<string, typeof response>); // 将对象的值转为数组,得到最终分组结果 const groupedResult = Object.values(result);
运行上述代码后,groupedResult的结构完全符合期望输出。
内容的提问来源于stack exchange,提问作者Александр Мерный
相关产品推荐
相关产品推荐

