JavaScript从对象数组生成嵌套树,同层级多子节点时递归逻辑失效如何解决?
问题原因分析
- 第一,你的
findNode递归逻辑存在核心缺陷:- 当节点存在子节点时,你没有先校验当前节点是否是要找的父节点,直接递归了最后一个子节点,跳过了当前节点的匹配逻辑
- 你仅递归了当前节点的最后一个子节点,没有遍历所有子节点,导致同层级的其他节点完全不会被检索,所以P1插入C2之后,再处理C1时,递归直接进入C2的子节点查找,不会判断P1本身就是C1的父节点,自然无法插入成功
- 第二,现有排序逻辑不完整:仅将顶级节点前置,没有保证子节点的处理顺序晚于父节点,如果子节点比父节点先被遍历,会出现找不到父节点无法插入的问题。
修正方案
方案1:最小改动修复原有逻辑
仅修改findNode函数,调整为遍历所有子节点、优先校验当前节点是否匹配的逻辑即可解决问题:
public findNode(ele, obj){ // 先校验当前节点是不是目标父节点 if(ele.name === obj.parentGroup){ ele.children.push({name: obj.groupName, children: []}); // 找到就返回,避免无效重复查找 return true; } // 遍历所有子节点递归查找 for(let child of ele.children){ if(this.findNode(child, obj)){ return true; } } return false; }
方案2:更高效的实现(推荐)
不需要提前排序,也不需要递归遍历整个树查找,用哈希表存储所有节点映射,两次遍历即可完成组装,时间复杂度仅为O(n),性能远高于原有递归查找方案:
function buildTree(inputs) { // 存储groupName到节点对象的映射表 const nodeMap = {}; // 存储最终的顶级节点数组 const rootNodes = []; // 第一次遍历:初始化所有节点,存入映射表 inputs.forEach(item => { nodeMap[item.groupName] = { name: item.groupName, children: [] }; }); // 第二次遍历:组装父子关系 inputs.forEach(item => { const currentNode = nodeMap[item.groupName]; if(item.parentGroup === "null"){ rootNodes.push(currentNode); }else{ nodeMap[item.parentGroup].children.push(currentNode); } }); return rootNodes; } // 调用示例 const finalArr = buildTree(inputs);
内容的提问来源于stack exchange,提问作者Lisa
相关产品推荐
相关产品推荐

