如何将JavaScript树形对象的所有节点转换为扁平数组?
优雅实现树形结构转扁平数组的方案
首先给出原始树形结构:
let tree = { id: 1, children: [ {id: 2}, {id: 3}, { id: 4, children: [ {id: 5}, {id: 6}, { id: 7, children: [ {id: 8}, {id: 9}, {id: 10} ] } ] } ] }
需求是将其转换为包含所有节点的扁平数组,每个节点保留自身的children结构(若存在),最终结果示例:
let flattenedTree = [ { id: 1, children: [ /* 所有子节点... */ ] }, { id: 2 }, { id: 3 }, { id: 4, children: [ /* 所有子节点... */ ] }, { id: 5 }, { id: 6 }, { id: 7, children: [ /* 所有子节点... */ ] }, { id: 8 }, { id: 9 }, { id: 10 } ]
以下是几种无需多层嵌套的优雅实现方案:
方案一:递归实现(简洁直观)
递归是处理树形结构最自然的方式,代码简洁易读,适合层级不深的场景:
function flattenTree(node) { const result = [node]; if (node.children) { node.children.forEach(child => { result.push(...flattenTree(child)); }); } return result; } // 使用示例 const flattenedTree = flattenTree(tree);
逻辑说明:先将当前节点加入结果数组,再递归处理每个子节点,将子节点的扁平结果展开后追加到数组中,没有冗余嵌套,逻辑清晰。
方案二:迭代实现(避免递归栈溢出)
如果树形结构层级极深,递归可能触发栈溢出,此时可借助栈或队列实现迭代遍历:
深度优先遍历(栈实现)
function flattenTreeIterative(node) { const stack = [node]; const result = []; while (stack.length > 0) { const current = stack.pop(); result.push(current); // 子节点倒序入栈,保证遍历顺序与递归一致 if (current.children) { for (let i = current.children.length - 1; i >= 0; i--) { stack.push(current.children[i]); } } } return result; }
广度优先遍历(队列实现)
若需要按层级顺序输出节点,可使用队列:
function flattenTreeBFS(node) { const queue = [node]; const result = []; while (queue.length > 0) { const current = queue.shift(); result.push(current); if (current.children) { queue.push(...current.children); } } return result; }
逻辑说明:通过手动维护栈/队列控制遍历流程,彻底避免递归栈溢出问题,代码结构清晰,无多层嵌套。
方案三:Generator函数(灵活可控)
利用Generator函数可实现惰性遍历,按需获取节点,也能轻松转换为数组:
function* traverseTree(node) { yield node; if (node.children) { for (const child of node.children) { yield* traverseTree(child); } } } // 转换为数组 const flattenedTree = [...traverseTree(tree)];
逻辑说明:通过yield逐个返回节点,yield*递归调用自身处理子节点,语法简洁,还支持按需迭代(无需一次性加载所有节点)。
内容的提问来源于stack exchange,提问作者user17196717
相关产品推荐
相关产品推荐

