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

如何通过递归遍历列表获取所有子节点及子子节点?求助修正代码

解决方法

你的递归函数问题在于将递归调用返回的数组直接作为元素推入结果,导致嵌套结构,而非扁平化的子节点列表。以下是修正后的实现:

基础递归实现(扁平化子节点列表)

const data = [
  { id: 1, parent: 0 },
  { id: 2, parent: 1 },
  { id: 3, parent: 1 },
  { id: 4, parent: 3 }
];

const getAllDescendants = (parentNode) => {
  let descendants = [];
  // 获取当前节点的直接子节点
  const children = data.filter(item => item.parent === parentNode.id);
  
  // 将直接子节点加入结果列表
  descendants.push(...children);
  
  // 递归获取每个子节点的后代并加入结果
  for (const child of children) {
    descendants.push(...getAllDescendants(child));
  }
  
  return descendants;
};

// 示例:获取id为1的节点的所有子节点及子子节点
console.log(getAllDescendants(data[0]));
// 输出: [ { id: 2, parent: 1 }, { id: 3, parent: 1 }, { id: 4, parent: 3 } ]

优化版本(预构建父节点映射提升性能)

如果数据量较大,每次递归都使用filter会影响效率。可以预先构建父节点到子节点的映射表:

const data = [
  { id: 1, parent: 0 },
  { id: 2, parent: 1 },
  { id: 3, parent: 1 },
  { id: 4, parent: 3 }
];

// 预构建父节点到子节点的映射
const parentChildrenMap = {};
data.forEach(item => {
  if (!parentChildrenMap[item.parent]) {
    parentChildrenMap[item.parent] = [];
  }
  parentChildrenMap[item.parent].push(item);
});

const getAllDescendantsEfficient = (parentNode) => {
  let descendants = [];
  // 直接从映射表获取子节点,无需重复过滤
  const children = parentChildrenMap[parentNode.id] || [];
  
  descendants.push(...children);
  
  for (const child of children) {
    descendants.push(...getAllDescendantsEfficient(child));
  }
  
  return descendants;
};

console.log(getAllDescendantsEfficient(data[0]));
// 输出与基础版本一致

原代码问题分析

  1. 嵌套数组问题:原代码中family.push(getNodes(sons))将递归返回的整个数组作为单个元素推入,导致结果嵌套。改为family.push(...getNodes(sons))可将数组元素逐个展开加入结果。
  2. 包含父节点问题:原逻辑在节点无后代时会将节点本身加入结果,但需求是获取子节点及子子节点,因此无需包含初始节点。修正后的逻辑从直接子节点开始收集,避免了这个问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:30:57