如何在Angular中使用RxJS按用户类型分组并求和指定属性

需求
我希望按用户类型(contractor或staff)对用户分组,同时对Unit(字数/小时)和Cost字段求和。
尝试的代码与错误输出
我写了下面这段代码,但没得到想要的结果:
this.jobsGroupBy = of(this.jobDetails).pipe( groupBy((val:any) => val.userId && val.cont), mergeMap((val$:any) => val$.pipe( reduce((acc:any, curr:any) => { acc.tCost = Number(acc.tCost) + Number(curr.tCost); this.jobsGroupBy = acc; return acc; }) ) ) ); console.log('result :'+ JSON.stringify(this.jobsGroupBy));
输出结果是:
result :{"source":{}}
问题分析与修正方案
你的代码存在三个核心问题:
- 分组逻辑错误:现在用
val.userId && val.cont作为分组key,这根本不是按contractor/staff类型分组的逻辑,应该直接取用户的类型标识(比如假设字段是userType,或者通过val.cont判断:val.cont ? 'contractor' : 'staff')。 - Observable未订阅就打印:你把Observable对象直接赋值给
this.jobsGroupBy后立即console.log,此时Observable还没执行,打印的只是Observable的结构,不是实际计算结果。 - 求和不完整:
reduce里只处理了tCost的求和,完全没管Unit字段,而且累加器没有初始值,会导致NaN问题。
修正后的代码如下:
// 假设jobDetails每个元素包含userType(contractor/staff)、unit、tCost字段 this.jobsGroupBy$ = of(this.jobDetails).pipe( mergeAll(), // 把数组拆成单个元素,因为of()会把整个数组当一个值传递 groupBy(item => item.userType), // 按用户类型分组 mergeMap(group$ => group$.pipe( reduce((acc, curr) => ({ userType: group$.key, totalUnit: acc.totalUnit + Number(curr.unit), totalCost: acc.totalCost + Number(curr.tCost) }), { totalUnit: 0, totalCost: 0 }) // 初始化累加器 ) ), toArray() // 把所有分组结果合并成一个数组 ); // 必须订阅Observable才能拿到计算结果 this.jobsGroupBy$.subscribe(result => { console.log('分组求和结果:', result); this.jobsGroupBy = result; // 把结果存到变量里 });
核心修正说明:
mergeAll():因为of(this.jobDetails)会把整个数组作为一个值发给groupBy,而groupBy需要逐个处理数组里的每个对象,所以必须用这个操作符拆分数组。- 分组条件:直接用用户类型字段作为分组key,确保分组逻辑正确。
- 累加器初始化:给
reduce传入初始值{ totalUnit: 0, totalCost: 0 },避免NaN,同时处理两个字段的求和。 toArray():把每个分组的结果收集成一个数组,方便后续展示或使用。- 订阅Observable:Observable只有被订阅才会执行计算,所以必须在
subscribe回调里获取结果,不能直接打印Observable对象。
内容的提问来源于stack exchange,提问作者user475391
相关产品推荐
相关产品推荐

