如何基于层级字符串Code将扁平化数组转为父子树形数组?
用层级Code将扁平化数组转树形结构的解决方案
我之前也碰到过用层级Code来构建树形结构的需求,递归确实是可行方案,不过咱们可以一步步拆解,把这个问题落地~
核心思路
核心逻辑就是利用Code的.分隔特性,拆解出每个节点的层级关系:
- 把每个节点的Code按
.拆分成层级数组(比如01.05.011拆成['01', '05', '011']) - 通过层级数组生成父级Code,找到对应的父节点后挂载
- 迭代或递归都能实现,先从更直观的迭代方案讲起,再补充递归版本
迭代方案(推荐,避免递归栈溢出)
步骤1:准备测试数据与初始化
先模拟一组扁平化数据,同时创建节点映射表(快速查找父节点)和根树数组:
// 测试用扁平化数组 const flatArray = [ { id: 1, code: '01', name: '一级节点1' }, { id: 2, code: '01.05', name: '二级节点1-1' }, { id: 3, code: '01.05.011', name: '三级节点1-1-1' }, { id: 4, code: '01.05.011.0001', name: '四级节点1-1-1-1' }, { id: 5, code: '02', name: '一级节点2' }, { id: 6, code: '02.03', name: '二级节点2-1' } ]; // 节点映射表:用code做key,存节点引用,方便快速查找父节点 const nodeMap = new Map(); // 最终的树形结构数组 const tree = [];
步骤2:遍历构建树形结构
逐个处理每个节点,拆分Code、找父节点、挂载:
flatArray.forEach(node => { // 复制原节点并添加children属性,避免修改原数据 const treeNode = { ...node, children: [] }; // 把当前节点存入映射表 nodeMap.set(treeNode.code, treeNode); const codeParts = treeNode.code.split('.'); // 一级节点(只有一个层级)直接加入根树 if (codeParts.length === 1) { tree.push(treeNode); } else { // 生成父级Code:去掉最后一个层级后拼接 const parentCode = codeParts.slice(0, -1).join('.'); // 从映射表中获取父节点 const parentNode = nodeMap.get(parentCode); // 找到父节点就挂载进去 if (parentNode) { parentNode.children.push(treeNode); } } }); // 打印结果,就能看到标准树形结构了 console.log(JSON.stringify(tree, null, 2));
递归版本实现
如果一定要用递归,记得先把节点按层级深度排序(浅层级在前),确保递归查找时父节点已被处理:
// 先按Code的层级深度排序,浅层级节点在前 const sortedArray = [...flatArray].sort((a, b) => { return a.code.split('.').length - b.code.split('.').length; }); // 递归构建树形结构的函数 function buildTree(nodes, parentCode = '') { const children = []; nodes.forEach(node => { const codeParts = node.code.split('.'); // 计算当前节点的父级Code const currentParentCode = codeParts.slice(0, -1).join('.'); // 如果当前节点的父级Code匹配传入的parentCode,就递归找它的子节点 if (currentParentCode === parentCode) { const childNode = { ...node, children: buildTree(nodes, node.code) }; children.push(childNode); } }); return children; } const recursiveTree = buildTree(sortedArray); console.log(JSON.stringify(recursiveTree, null, 2));
关键注意事项
- Code唯一性:必须保证每个Code是唯一的,否则映射表会覆盖重复Code的节点,导致数据丢失
- 排序必要性:递归版本一定要先排序,否则父节点可能还没被处理,递归时找不到
- 容错处理:如果数据中存在父级Code缺失的节点,可以根据需求添加逻辑(比如直接作为根节点,或者打印警告跳过)
内容的提问来源于stack exchange,提问作者Teguh Santoso
相关产品推荐
相关产品推荐

