You need to enable JavaScript to run this app. JavaScript中如何通过forEach将数组转换为指定嵌套键值对结构
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript中如何通过forEach将数组转换为指定嵌套键值对结构

JavaScript 数组嵌套结构转换(基于forEach实现)

原始数据

const data = [
  {
    "id": 1,
    "name": "john",
    "income": 22000,
    "expenses": 15000
  },
  {
    "id": 2,
    "name": "kiran",
    "income": 27000,
    "expenses": 13000
  },
  {
    "id": 1,
    "name": "john",
    "income": 35000,
    "expenses": 24000
  }
]

目标输出要求

将扁平的、存在重复name的原始数组,转换为按非重复name组织的嵌套结构:

  • 每个输出条目对应一个唯一name
  • 条目下的series数组,将原数据里的income、expenses字段转换为固定格式的对象{name: 字段名, value: 对应数值}
  • 输出长度为2,john、kiran各占一个条目,和提供的示例结构完全匹配

常见实现问题

之前用forEach无法得到预期输出,通常是两个原因:

  • 未对重复name做去重判断,直接逐元素push到结果数组,导致出现两个john的重复条目
  • 未将条目下的income、expenses扁平字段,转换为series数组内的标准嵌套对象结构

核心实现逻辑

  1. 提前初始化空的结果数组,以及用于去重判断的临时映射对象,避免重复生成条目
  2. 逐一遍历原始数组元素:
    • 遇到已经在映射里登记过的name,直接跳过(和示例输出的逻辑保持一致,即只保留首次出现的name对应的数值)
    • 首次遇到的name,按照目标结构生成嵌套对象,存入映射并加入结果数组

可直接运行的代码

const result = [];
// 临时映射,记录已经处理过的name,实现去重
const processedNames = {};

data.forEach((item) => {
  // 已处理过的name直接跳过,和示例输出结构完全匹配
  if (processedNames[item.name]) return;

  // 生成符合目标结构的条目
  const targetEntry = {
    name: item.name,
    series: [
      { name: "income", value: item.income },
      { name: "expenses", value: item.expenses }
    ]
  };

  processedNames[item.name] = true;
  result.push(targetEntry);
});

注:如果实际需求是要把同name的所有历史记录都纳入series(即把第三条john的35000、24000也追加到john的series数组里),只需要调整分支判断逻辑,把已存在条目的新数值直接push到对应series数组即可,不需要改动整体遍历框架。

方案优势

  • 仅需一次全量遍历,时间复杂度为O(n),无需嵌套循环查找重复项,是这类转换场景的最优实现方式
  • 逻辑直白,不需要复杂的数组方法嵌套,完全基于forEach实现,可读性强
  • 通过映射对象做状态管理,不用每次循环遍历结果数组找匹配项,减少代码出错概率

内容的提问来源于stack exchange,提问作者Krithi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 02:24:04