前言
list与树形结构相互转换在前端业务处理中比较常见,如菜单、virtual dom处理等,一个好的数据处理方式是前端必备的知识。
list转为树形结构
树形结构的数据结构解析:树形结构父元素与子元素必定有一个联系,在此我们假定父元素与子元素的联系为id与parentId,且根元素应无parentId或parentId为null/'',即没有父级元素指向。
-
数据结构转换思路:
- 首先,遍历一次list,得到根元素对象集合,并在list中剔除根元素对象。得到的是根元素对象集合的原因是可能出现多个根节点对象,如菜单。
- 其次,再次遍历list,得到parentId与子节点映射关系
{parentId:[child1,child2,...]}//注:此处可以用Map结构
。 - 最后,通过parentId与子节点映射关系,递归组装属性结构。
-
代码展示:
lineConvertToTree(list=[]) { let rootArr = [],childListToKeyValue={}; if (!utils.isArray(list)) return rootArr; // 组装根节点 for(let i=0;i<list.length;i++){ if(list[i].parentId===null||list[i].parentId===undefined&&list[i].parentId===''){ rootArr.push(...list.splice(i,1)); i--; } } // 将子节点转为key:value对象 for(let i=0;i<list.length;i++){ if(!childListToKeyValue[list[i].parentId]){ childListToKeyValue[list[i].parentId]=[]; } childListToKeyValue[list[i].parentId].push(list[i]); } // 多个树集合 for(let i=0;i<rootArr.length;i++){ // todo 递归:借助一个数组,将相关数据集合在一起、循环,达到递归作用 let currentChildren=[rootArr[i]]; // 通过id与parentId对应关系,组成tree结构 while(currentChildren.length>0){ let currentNode=currentChildren.shift(); currentNode.children=childListToKeyValue[currentNode.id]?childListToKeyValue[currentNode.id]:[]; currentChildren=[...currentChildren,...currentNode.children]; } } return rootArr;
树形结构转为list
- 转换思路:递归树形结构即可。
-
代码展示:
treeCovertToLine(root={}){ let list=[],queue=[]; if(!utils.isObject(root)) return list; queue.push(root); while(queue.length>0){ let currentNode=queue.shift(); if(currentNode.children&¤tNode.children.length>0){ queue=[...queue,...currentNode.children]; } delete currentNode.children; list.push(currentNode); } return list;
参考网站:
线性结构与树形结构相互转换(ES6实现):https://blog.csdn.net/weixin_...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。