如何递归遍历嵌套对象数组,匹配ID后插入子对象数组?
嵌套对象数组的深层节点插入优化
我有如下格式的JavaScript对象数组:
let obj = [ { children: [ { children: [], data: { name: "aaa", id: "234" }, key: "234" }, { children: [], data: { name: "bbb", id: "456" }, key: "456" }, { children: [], data: { name: "ccc", id: "789" }, key: "789" }, ], data: { name: "ddd", id: "123" }, key: "123", }, { children: [], data: { name: "eee", id: "411" }, key: "411" }, { children: [], data: { name: "fff", id: "412" }, key: "412" }, ]
我需要将一个同结构的对象数组插入到ID为789的节点的children数组中。我尝试了以下写法,但仅能处理到第二层结构:
obj.map((emp) => { if (emp.data.id === idIwantToInsert) { emp.children.push(arrayofobjectsIwanttoInsert) } else { emp.children.map((citem) => { if (citem.data.id === idIwantToInsert) { citem.children.push(arrayofobjectsIwanttoInsert) } }) } })
请问有没有优化的方法,可以检查任意深度嵌套的对象数组中的目标ID并完成插入?
解决方案:递归遍历处理任意深度嵌套
可以用递归函数遍历整个嵌套数组,找到目标ID的节点后完成插入,这种方法能适配任意层级的嵌套结构,比固定层级的遍历更灵活。
实现代码
function insertIntoTargetNode(nodes, targetId, insertArray) { // 遍历当前层级的所有节点 for (const node of nodes) { // 匹配到目标节点,完成插入 if (node.data.id === targetId) { // 用扩展运算符将插入数组的元素逐个加入children,避免把整个数组作为单个元素插入 node.children.push(...insertArray); // 找到目标后直接返回,终止后续遍历 return true; } // 当前节点有子节点,递归遍历子节点 if (node.children.length > 0) { const found = insertIntoTargetNode(node.children, targetId, insertArray); if (found) return true; } } // 遍历完所有节点未找到目标 return false; } // 使用示例 const idIwantToInsert = "789"; const arrayofobjectsIwanttoInsert = [ { children: [], data: { name: "new1", id: "1001" }, key: "1001" }, { children: [], data: { name: "new2", id: "1002" }, key: "1002" } ]; // 执行插入 insertIntoTargetNode(obj, idIwantToInsert, arrayofobjectsIwanttoInsert);
代码说明
- 递归遍历:从顶层节点开始,逐层检查每个节点,若当前节点不是目标,则递归遍历其子节点,直到找到目标或遍历结束。
- 提前终止:找到目标节点后立即返回,避免不必要的遍历,提升性能。
- 数组展开:使用
...insertArray拆分插入数组的元素,确保每个元素都是目标节点的独立子节点;如果需要将整个数组作为单个子节点插入,去掉扩展运算符即可。
迭代式替代方案(避免深层递归栈溢出)
如果嵌套层级极深(比如超过1000层),递归可能引发栈溢出,这时可以用迭代的深度优先遍历实现:
function insertIntoTargetNodeIterative(nodes, targetId, insertArray) { const stack = [...nodes]; while (stack.length > 0) { const node = stack.pop(); if (node.data.id === targetId) { node.children.push(...insertArray); return true; } // 将子节点压入栈,继续遍历 stack.push(...node.children); } return false; }
内容的提问来源于stack exchange,提问作者new star
相关产品推荐
相关产品推荐

