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

优化JavaScript中多reduce和map提取嵌套对象数据的方法

优化嵌套对象数组的数据提取代码

嘿,你的代码功能没问题,但确实可以通过JS的现代特性让它更简洁优雅!先把你没写完的代码补全(假设你是要提取学校名称和地址详情),然后给你几个优化方案:


你的原始代码(补全后)

我正在从嵌套对象数组中提取数据,当前用两个reduce加map的方式实现,功能正常但代码不够优雅。请问如何优化这段代码?

我的代码如下:

function extractSchools(schools) {
  let schoolData = [];
  if (schools) {
    schoolData = schools.reduce(function(parentdata, chlrn) {
      let childrenlist = chlrn.children;
      let childrendata = [];
      if (childrenlist) {
        childrendata = childrenlist.reduce(function(addrsslist, school) {
          return addrsslist.concat(school.address.map(i => ({
            schoolName: school.name,
            addressDetail: i.detail,
            city: i.city
          })));
        }, []);
      }
      return parentdata.concat(childrendata);
    }, []);
  }
  return schoolData;
}

优化方案1:用flatMap替代嵌套reduce+concat

flatMap是专门用来处理“映射后扁平化”的场景,完美匹配你现在的嵌套遍历需求,代码会清爽很多:

function extractSchools(schools) {
  if (!schools) return [];
  
  return schools.flatMap(chlrn => {
    // 如果当前项没有children,直接返回空数组跳过
    if (!chlrn.children) return [];
    // 遍历子学校,再遍历每个学校的地址,最后扁平化结果
    return chlrn.children.flatMap(school => 
      school.address.map(i => ({
        schoolName: school.name,
        addressDetail: i.detail,
        city: i.city
      }))
    );
  });
}

为什么这更好?

  • 去掉了一堆冗余的临时变量(比如parentdata、childrendata),逻辑链更清晰
  • flatMap的语义很直观:先把每个父元素映射成子数组,再把所有子数组合并成一个大数组,完全对应你“取父级→取子学校→取地址”的流程
  • 提前做空值判断,避免无效遍历

优化方案2:用可选链+箭头函数进一步精简(ES2020+)

如果你的项目环境支持ES2020及以上的语法,用可选链(?.)和空值合并(??)可以把代码压缩得更紧凑,同时可读性依然在线:

const extractSchools = (schools) => 
  schools?.flatMap(chlrn => 
    chlrn.children?.flatMap(school => 
      school.address.map(i => ({
        schoolName: school.name,
        addressDetail: i.detail,
        city: i.city
      }))
    ) ?? []
  ) ?? [];

亮点

  • 箭头函数让代码更简洁,去掉了冗余的function和大括号
  • 可选链?.自动处理schools、chlrn.children为null/undefined的情况,不用写一堆if判断
  • 空值合并??确保空值场景下返回空数组,保证函数返回值始终是数组类型

优化方案3:通用递归提取(适配更深嵌套)

如果未来你的数据结构可能有多层嵌套的children,写一个递归函数会更灵活,不用每次加层级都改代码:

function extractSchools(schools) {
  if (!schools) return [];
  
  // 定义递归提取的辅助函数
  const extractItems = (items) => items.flatMap(item => {
    // 如果当前项有children,递归处理子项
    if (item.children) {
      return extractItems(item.children);
    }
    // 处理最底层的学校地址
    return item.address?.map(i => ({
      schoolName: item.name,
      addressDetail: i.detail,
      city: i.city
    })) ?? [];
  });
  
  return extractItems(schools);
}

适用场景

  • 数据结构的嵌套层级不固定,可能有3层甚至更多的children
  • 希望代码有扩展性,未来结构变化时不用大改核心逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:15:03