如何在JavaScript中通过parentId和Id将扁平数组转为树形数组?
实现扁平数组转树形结构的两种常用方法
嘿,这个需求我做项目时经常碰到,把扁平数组转成树形结构其实不难,这里给你分享两种实用的实现思路,你可以根据自己的场景选择:
方法一:利用哈希表(Map)快速查找父节点(高效推荐)
这种方法时间复杂度是O(n),不管数据量多大都能高效处理,核心是先把所有节点存到Map里,再遍历每个节点找到父节点并添加到children中:
function flatToTree(arr) { // 创建Map存储每个节点,方便快速查找 const nodeMap = new Map(); // 存放最终的树形结构(根节点集合) const tree = []; // 第一步:把所有节点存入Map,同时初始化children属性 arr.forEach(node => { nodeMap.set(node.id, { ...node, children: [] }); }); // 第二步:遍历节点,将子节点挂载到对应父节点下 arr.forEach(node => { if (node.pid !== null) { const parent = nodeMap.get(node.pid); parent.children.push(nodeMap.get(node.id)); } else { // pid为null的是根节点,直接加入树形数组 tree.push(nodeMap.get(node.id)); } }); return tree; } // 测试你的数据 const a = [ {id: 1, pid: null}, {id: 2, pid: 1}, {id: 3, pid: 1}, {id: 4, pid: 3}, {id: 5, pid: 3} ]; const result = flatToTree(a); console.log(result);
运行后输出的结果完全符合你的期望~
方法二:递归查找父节点(适合小数据量,逻辑直观)
如果你的数据量不大,递归方式会更直观易懂,核心是每次递归找到当前节点的所有子节点:
function flatToTreeRecursive(arr, pid = null) { // 过滤出当前pid对应的子节点,再递归查找每个子节点的子节点 return arr.filter(node => node.pid === pid).map(node => ({ ...node, children: flatToTreeRecursive(arr, node.id) })); } // 测试 const a = [ {id: 1, pid: null}, {id: 2, pid: 1}, {id: 3, pid: 1}, {id: 4, pid: 3}, {id: 5, pid: 3} ]; const result = flatToTreeRecursive(a); console.log(result);
这个方法逻辑简单:先筛选出对应父id的节点,再对每个节点递归生成子树。不过要注意,数据量大时递归的性能会比第一种方法差,因为每次filter都会遍历整个数组。
补充说明
- 两种方法都会自动给每个节点添加
children属性,没有子节点时就是空数组,和你期望的输出格式一致。 - 如果数组里有多个根节点(多个
pid为null的节点),两种方法都能正确处理,会把所有根节点都放到结果数组中。
内容的提问来源于stack exchange,提问作者Xinyi Li
相关产品推荐
相关产品推荐

