本文介绍把平铺的数组转成数形数组的两种方法,分别是非递归和递归方法,包含代码和具体的推演过程
我们这里的平铺数组有三个属性:id、pid、name;其中pid决定着这个对象的父级,id决定着这个对象的子级,口有阐述可能难以表达清楚,我们看一下一个简单的小例子:
[
{id:"01", pid:"", name:"老王" }, // 没有pid代表没有父级,这个对象是顶级
{id:"02", pid:"01", name:"小张" }
]
// 上面的结构说明: 老王是小张的上级
一、非递归方法:
- 优点是相对来说更好了解,缺点是会改变原数组
// 把平铺的数组 转成 树形结构
const function arrryToTree(arr) {
// 1. 定义两个变量
const treeList = [] // 树状数据数组
const map = {} // 存储映射关系
// 2. 建立一个映射关系,并给每个元素补充children属性,key是id值,value是对象本身
// 映射关系: 目的是让我们能通过id快速找到对应的元素
// 补充children:让后边的计算更方便
arr.forEach(item => {
if (!item.children) {
item.children = []
}
map[item.id] = item
})
// 3. 对于每一个元素来说,先找它的上级
// 如果能找到,说明它有上级,则要把它添加到上级的children中去
// 如果找不到,说明它没有上级,直接添加到 treeList
arr.forEach(item => {
const parent = map[item.pid]
if (parent) {
parent.children.push(item) // 如果存在上级则表示item不是最顶层的数据
} else {
treeList.push(item) // 如果不存在上级 则是顶层数据,直接添加
}
})
return treeList // 返回
}
- 上述代码的推衍过程
// 1. 原平铺数组对象
arr = [
{ id: '29', pid: '', name: '总裁办' },
{ id: '2c', pid: '', name: '财务部' },
{ id: '2d', pid: '2c', name: '财务核算部'},
{ id: '2f', pid: '2c', name: '薪资管理部'},
{ id: 'd2', pid: '', name: '技术部'},
{ id: 'd3', pid: 'd2', name: 'Java研发部'}
]
// 2. 将id作用key建立映射关系 并补充children属性
treeList: []
map: {
'29': { id: '29', pid: '', name: '总裁办', children:[] },
'2c': { id: '2c', pid: '', name: '财务部', children:[] }
'2d': { id: '2d', pid: '2c', name: '财务核算部', children:[] },
'2f': { id: '2f', pid: '2c', name: '薪资管理部', children:[] },
'd2': { id: 'd2', pid: '', name: '技术部', children:[] },
'd3': { id: 'd3', pid: 'd2', name: 'Java研发部', children:[] }
}
// 3. 根据pid判断有无上级 生成树状数组
treeList: [
{ id: '29', pid: '', 'name': '总裁办' }
{ id: '2c', pid: '', 'name': '财务部', children:[{ id: '2d', pid: '2c', 'name': '财务核算部'},{ id: '2f', pid: '2c', 'name': '薪资管理部'} }
{ id: 'd2', pid: '', 'name': '技术部', children:[{ id: 'd3', pid: 'd2', 'name': 'Java研发部'}]}
]
二、递归方法
- 优点是不会改变原数组
function arrryToTree(arr,pid=''){
// 在list中根据pid来找元素
let treeList = []
// 过滤出来pid=''的就是顶层
treeList = arr.filter(item => item.pid === pid)
// 在通过循环加递归的方法将第二层和第三层放入到children中
treeList.forEach(item => {
item.children = arrryToTree(arr,item.id)
})
return treeList
}
- 上述代码的推衍过程
// 1. 原平铺数组对象
arr = [
{ id: '29', pid: '', name: '总裁办' },
{ id: '2c', pid: '', name: '财务部' },
{ id: '2d', pid: '2c', name: '财务核算部'},
{ id: '2f', pid: '2c', name: '薪资管理部'},
{ id: 'd2', pid: '', name: '技术部'},
{ id: 'd3', pid: 'd2', name: 'Java研发部'}
]
// 2. 根据pid过滤出顶层
treeList: [
{ id: '29', pid: '', name: '总裁办' },
{ id: '2c', pid: '', name: '财务部' },
{ id: 'd2', pid: '', name: '技术部'},
]
// 3. 通过循环,将pid===treeList中id的对象push到children中
treeList: [
{ id: '29', pid: '', 'name': '总裁办' }
{ id: '2c', pid: '', 'name': '财务部', children:[{ id: '2d', pid: '2c', 'name': '财务核算部'},{ id: '2f', pid: '2c', 'name': '薪资管理部'} }
{ id: 'd2', pid: '', 'name': '技术部', children:[{ id: 'd3', pid: 'd2', 'name': 'Java研发部'}]}
]