Angular中如何通过reduce函数返回符合要求的对象数组
解决方法
问题原因
- 当前
reduce的初始值为空对象{},累加逻辑也是直接给对象设置键值对,最终自然返回的是键值对结构的对象,而非目标数组 - 另外注意
this.activities$是异步流,你当前把this.aggregated的计算写在subscribe外面,会出现还没拿到接口返回的dati就先执行了计算的问题,导致结果为空
调整后代码
优先推荐下面的实现,时间复杂度更低:
this.activities$ // 原代码里的pipe(map((e) => e.map((e) => e)))没有实际作用,可直接删除 .subscribe((e) => { this.dati = e; // 计算逻辑移到subscribe内部,保证拿到的是接口返回的最新数据 this.aggregated = Object.entries( this.dati.reduce((acc: Record<string, number>, activity) => { const projectName = `${activity.project?.customer.name} - ${activity.project?.name}`; // 第一步先按项目名分组统计工时,和你原有逻辑一致 acc[projectName] = (acc[projectName] ?? 0) + activity.hours; return acc; }, {}) // 第二步把统计完的键值对转换为目标数组结构 ).map(([projectName, hours]) => ({ project: projectName, hours: hours })); });
如果一定要纯用reduce一步完成,也可以用下面的写法:
this.aggregated = this.dati.reduce((acc: {project: string, hours: number}[], activity) => { const projectName = `${activity.project?.customer.name} - ${activity.project?.name}`; // 查找累加数组中是否已经存在当前项目 const existProject = acc.find(item => item.project === projectName); if (existProject) { // 存在就叠加工时 existProject.hours += activity.hours; } else { // 不存在就往数组新增一项 acc.push({ project: projectName, hours: activity.hours }) } return acc; }, []); // 初始值设置为空数组
说明
第一种实现对象查找的时间复杂度为O(1),整体复杂度仅为O(n),数据量较大时性能更好;第二种纯reduce实现每次需要遍历数组查找项目,复杂度为O(n²),仅适合数据量小的场景使用。
内容的提问来源于stack exchange,提问作者Man24
相关产品推荐
相关产品推荐

