如何在JavaScript/TypeScript(Json/Angular)中按相同值分组对象并保留差异值
在JavaScript/TypeScript(Angular)中按libele分组对象并保留差异字段
原始响应数据
{ "Dispositif": [ { "libele": "AAA", "Fonds": "xxx", "Estimation": "122", "Parts": "11" }, { "libele": "AAA", "Fonds": "yyy", "Estimation": "111", "Parts": "12" }, { "libele": "BBB", "Fonds": "zzz", "Estimation": "111", "Parts": "12" }, { "libele": "BBB", "Fonds": "aaa", "Estimation": "111", "Parts": "12" }, { "libele": "CCC", "Fonds": "aaa", "Estimation": "111", "Parts": "12" } ] }
期望分组结果
{ "Dispositif" : [ { "libele": "A", "data": [ {"Fonds": "xxx","Estimation": "122","Parts": "11"},{"Fonds": "yyy","Estimation": "111","Parts": "12"}] }, { "libele": "B", "data": [ {"Fonds": "zzz","Estimation": "111","Parts": "12"},{"Fonds": "aaa","Estimation": "111","Parts": "12"}] }, { "libele": "C", "data": [ {"Fonds": "aaa","Estimation": "111","Parts": "12"}] } ] }
解决方案
1. 纯JavaScript实现
用Array.reduce()完成分组,再转换为目标结构:
const response = { "Dispositif": [ { "libele": "AAA", "Fonds": "xxx", "Estimation": "122", "Parts": "11" }, { "libele": "AAA", "Fonds": "yyy", "Estimation": "111", "Parts": "12" }, { "libele": "BBB", "Fonds": "zzz", "Estimation": "111", "Parts": "12" }, { "libele": "BBB", "Fonds": "aaa", "Estimation": "111", "Parts": "12" }, { "libele": "CCC", "Fonds": "aaa", "Estimation": "111", "Parts": "12" } ] }; // 按原始libele分组,收集差异字段 const grouped = response.Dispositif.reduce((acc, item) => { const key = item.libele; if (!acc[key]) acc[key] = []; const { libele, ...rest } = item; acc[key].push(rest); return acc; }, {}); // 转换为期望的结构,libele取首字母 const result = { Dispositif: Object.entries(grouped).map(([origLibele, data]) => ({ libele: origLibele.charAt(0), data })) }; console.log(result);
2. TypeScript/Angular实现
如果是处理Angular HTTP请求返回的数据,结合RxJS操作符处理:
import { map } from 'rxjs/operators'; import { HttpClient } from '@angular/common/http'; // 定义类型约束 interface OriginalItem { libele: string; Fonds: string; Estimation: string; Parts: string; } interface GroupedItem { libele: string; data: Omit<OriginalItem, 'libele'>[]; } interface ApiResponse { Dispositif: OriginalItem[]; } interface GroupedResponse { Dispositif: GroupedItem[]; } // 在组件/服务中使用 constructor(private http: HttpClient) {} getGroupedData() { this.http.get<ApiResponse>('你的API地址') .pipe( map(res => { // 分组逻辑 const groupedMap = res.Dispositif.reduce((acc, item) => { const key = item.libele; if (!acc[key]) acc[key] = []; const { libele, ...rest } = item; acc[key].push(rest); return acc; }, {} as Record<string, Omit<OriginalItem, 'libele'>[]>); // 转换为目标结构 return { Dispositif: Object.entries(groupedMap).map(([origKey, data]) => ({ libele: origKey.charAt(0), data })) } as GroupedResponse; }) ) .subscribe(groupedData => { console.log('分组结果:', groupedData); // 后续业务逻辑 }); }
关键逻辑说明
- 用
reduce遍历数组,以原始libele为键,把每个对象去掉libele后存入对应数组 - 最后把分组后的对象转为数组,同时将原始
libele转为首字母(如果不需要这个转换,直接用origKey即可)
内容的提问来源于stack exchange,提问作者Sarra
相关产品推荐
相关产品推荐

