You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:51:13