本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
这是一个常见的内容,如何将线性的数据转化为树型对象,我们需要一种思路,一种递归的思想,本文主要是介绍这种思想。
完整代码和结果
const arr = [
{ name: '内容1', fid: 0, id: 0, },
{ name: '内容2', fid: 0, id: 1, },
{ name: '内容3', fid: 0, id: 2, },
{ name: '内容4', fid: 1, id: 3, },
{ name: '内容5', fid: 1, id: 4, },
{ name: '内容6', fid: 2, id: 5, },
]
const res = []
// 两个入参 一个是线性对象数组,一个是目标对象
const addChild = (arr, obj) => {
// 目标对象的fid
const { fid } = obj
// 遍历线性对象数组
arr.forEach(cur => {
// 取出遍历的对象的id
const { id } = cur
// 判断是否是目标对象的fid
if (fid === id) {
// 如果是,先判断加上child指针
cur.child ? null : cur.child = []
// 如果加过了,直接加进子级数组
cur.child.push(obj)
} else if (cur.child) {
// 存在子级对象数组,就得判断子级有没有目标对象的父级
addChild(cur.child, obj)
}
});
}
arr.map(cur => {
const { id, fid } = cur
if (id === fid) {
res.push(cur)
} else {
addChild(res, cur)
}
})
console.log(res)
思想理解
我肯定不能保证你的线性数据结构与我这里的相同,因此我们重点是掌握一种递归的思路,怎么一步步完成。
创建线性数据
在创建线性数据时我们就应该为树状数据的转化做准备,什么准备呢?
const arr = [
{ name: '内容1', fid: 0, id: 0, },
{ name: '内容2', fid: 0, id: 1, },
{ name: '内容3', fid: 0, id: 2, },
{ name: '内容4', fid: 1, id: 3, },
{ name: '内容5', fid: 1, id: 4, },
{ name: '内容6', fid: 2, id: 5, },
]
比如我创造一个这样的数据,fid表示它父级节点的id。
特点就是id按顺序排列,且父节点的id会小于子节点的id。
这样我们就可以很容易的生成树状结构,不必担心自己的父级节点比自己晚遍历到,不会造成找不到父级节点的情况。
创建一个结果数组
const res = []
找到根节点
我们创建了结果数组,树也许不好整,但是把根种下去还是容易吧。
比如你可以提前标好type,我这里是定义自己id与fid相等的为根节点。
我们遍历数据,把定义好的根加入
arr.map(cur => {
const { id, fid } = cur
if (id === fid) {
res.push(cur)
} else {
...
}
})
接下来就是考虑..到底是什么呢,如果不是根,那这个目标对象就是有父节点的了。
既然有父节点,我们就把结果数组遍历一遍找找有没有对应的目标对象的父节点。
我们就需要创建一个找父级的方法。
可能需要两个入参,一个结果数组也就是一个对象数组,和一个正在找父级的目标对象
addChild(arr,obj)
创建递归方法
我们希望在一个线性的对象数组里找到其中的一个对象,是我们某个目标对象的父级节点。
如果是找到了,就给父级节点加入子级指针指向目标对象。
// 两个入参 一个是线性对象数组,一个是目标对象
const addChild = (arr, obj) => {
// 目标对象的fid
const { fid } = obj
// 遍历线性对象数组
arr.forEach(cur => {
// 取出遍历的对象的id
const { id } = cur
// 判断是否是目标对象的fid
if (fid === id) {
// 如果是,先判断加上child指针
cur.child ? null : cur.child = []
// 如果加过了,把目标对象直接加进遍历对象的子级数组
cur.child.push(obj)
}
});
}
如果不是呢?不是的话就不加了吗,肯定不行。
因为即便当前的遍历对象不是目标对象的父级节点,我们不能保证遍历对象的子级对象数组中没有目标对象的节点。
那么怎么判断子级对象数组有没有呢?
我们发现又是在一个对象数组里面找,所以我们还是调用同样的方法,这就是递归了。
// 两个入参 一个是线性对象数组,一个是目标对象
const addChild = (arr, obj) => {
// 目标对象的fid
const { fid } = obj
// 遍历线性对象数组
arr.forEach(cur => {
// 取出遍历的对象的id
const { id } = cur
// 判断是否是目标对象的fid
if (fid === id) {
// 如果是,先判断加上child指针
cur.child ? null : cur.child = []
// 如果加过了,直接加进子级数组
cur.child.push(obj)
} else if (cur.child) {
// 存在子级对象数组,就得判断子级有没有目标对象的父级
addChild(cur.child, obj)
}
});
}
尾言
如果觉得文章对你有帮助的话,欢迎点赞收藏哦,有什么错误或者意见建议也可以留言,感谢~