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

如何将扁平对象数组转换为支持深度嵌套的树形结构数组

如何将扁平对象数组转换为嵌套树形结构

嘿,这个需求我之前做项目的时候经常碰到,其实实现起来思路很清晰,而且能轻松支持任意深度的嵌套。下面我给你分享一个高效的实现方法:

核心思路

  • 首先创建一个节点映射表,用每个节点的id作为键,节点本身作为值,这样能在O(1)的时间内快速找到任意节点,避免频繁遍历数组浪费性能。
  • 遍历所有节点,把每个节点挂载到它对应的父节点的sub数组中;如果节点的parent是null,就把它直接加入最终的树形结果数组。

代码实现(JavaScript)

function buildTree(flatArray) {
  const nodeMap = new Map();
  const tree = [];

  // 第一步:将所有节点存入映射表,同时初始化每个节点的sub数组
  flatArray.forEach(node => {
    // 拷贝节点避免修改原数据,也可以直接用node.sub = [](会修改原数组)
    nodeMap.set(node.id, { ...node, sub: [] });
  });

  // 第二步:遍历节点,把每个节点挂载到父节点的sub数组中
  flatArray.forEach(node => {
    const currentNode = nodeMap.get(node.id);
    if (node.parent === null) {
      // 根节点直接加入结果树
      tree.push(currentNode);
    } else {
      const parentNode = nodeMap.get(node.parent);
      // 防止数据中存在无效的parent值,避免报错
      if (parentNode) {
        parentNode.sub.push(currentNode);
      }
    }
  });

  return tree;
}

代码解释

  • 用Map做映射表比普通对象更灵活,不管你的id是数字、字符串还是其他类型都能正常工作。
  • 提前初始化每个节点的sub数组,后续不需要再判断sub是否存在,简化逻辑。
  • 加入了if (parentNode)的判断,防止输入数组里出现不存在的parent值导致程序报错,增强鲁棒性。
  • 如果不需要保留原数组的节点,可以去掉扩展运算符{ ...node },直接给原节点添加sub属性,这样内存占用会更低。

测试示例

用你给出的测试数据来验证:

const flatData = [
  { id: 1, parent: null, title: 'test' },
  { id: 2, parent: 1, title: 'test2' },
  { id: 3, parent: 2, title: 'test3' },
  { id: 4, parent: 1, title: 'test4' } // 新增一个兄弟节点测试
];

const treeResult = buildTree(flatData);
console.log(treeResult);

输出的树形结构就是你想要的样子,而且不管嵌套多少层都能正确处理。

额外说明

  • 这个函数支持多个根节点(也就是多个parent为null的节点),所有根节点都会被包含在结果数组中。
  • 时间复杂度是O(n),只需要遍历数组两次,处理大数据量的时候性能也很出色。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 18:47:31