如何使用RxJS基于两个属性对对象数组进行分组?
基于RxJS实现多属性分组的解决方案
这个问题很常见——当你需要基于多个属性分组时,关键是要给groupBy提供一个能唯一标识属性组合的键。你原来的代码用单个id属性作为分组键没问题,但多个属性的话,直接返回对象会因为引用比较的问题导致分组失败,所以我们需要换一种方式生成键。
核心思路
groupBy的键选择器函数需要返回一个原始类型值(字符串、数字等),这样RxJS才能正确判断两个项是否属于同一组。对于多个属性,我们可以把它们拼接成一个唯一的字符串,或者用JSON.stringify把属性组合转换成字符串(前者性能更好)。
修改后的代码示例
下面是针对你的需求调整后的代码,会按age和weight两个属性分组,最终输出你想要的嵌套数组结构:
import { Observable } from 'rxjs'; import { groupBy, flatMap, reduce } from 'rxjs/operators'; // 定义数据类型(可选,但能提升类型安全性) interface Obj { id: number; age: number; weight: number; } Observable.of<Obj>( {id: 1, age: 5, weight: 145}, {id: 9, age: 7, weight: 10}, {id: 2, age: 5, weight: 145}, {id: 60, age: 11, weight: 145} ).pipe( // 用age和weight拼接成唯一字符串作为分组键 groupBy(item => `${item.age}-${item.weight}`), // 把每组的数据收集成数组,这里只保留id;若需要整个对象,换成 [...acc, item] 即可 flatMap(group$ => group$.reduce((acc, item) => [...acc, item.id], [])) ).subscribe(result => console.log(result));
预期输出
运行这段代码后,控制台会输出:
[1, 2] [9] [60]
完全符合你想要的[[1,2],[9],[60]]结构(订阅时会逐个输出每组数组,最终组合起来就是目标嵌套数组)。
补充说明
- 不要用数组或对象作为分组键(比如
groupBy(item => [item.age, item.weight])),因为JavaScript中对象/数组是按引用比较的,即使内容相同,不同的引用会被视为不同的键,导致分组错误。 - 如果需要更复杂的属性组合,可以用
JSON.stringify({age: item.age, weight: item.weight})生成键,但拼接字符串的性能会更优。
内容的提问来源于stack exchange,提问作者Aisatora
相关产品推荐
相关产品推荐

