关系表转化为树形对象

我们表明家族之间的父子关系可以有很多方式,常见的有两种,一种是较为形象的树型图,比如下面这种:

 另一种是关系表,比如下图这种:

 我们可以将上面两种形式在js分别定义为一个树型对象和数组:

//树形对象
const family = {
    name:"曹操",
    children:[
        {
            name:'曹植',
            children:[
                {
                    name:"曹光",
                },
                {
                    name:"曹满",
                }
            ]
        },
        {
            name:'曹丕',
            children:[
                {
                    name:"曹睿",
                },
                {
                    name:"曹言",
                }
            ]
        }
    ]
}
//关系表对应的数组
const list = [
    {name:"曹操",parent:''},
    {name:'曹植',parent:'曹操'},
    {name:'曹丕',parent:'曹操'},
    {name:'曹光',parent:'曹植'},
    {name:'曹满',parent:'曹植'},
    {name:'曹睿',parent:'曹丕'},
    {name:'曹言',parent:'曹丕'}
]

问题是:在大多数情况下,表明关系的时候,我们拿到的大多数是关系表数组而不是第一种树形对象 (因为:一是关系表数组存贮起来只需要几行,而树形对象存贮起来需要很多行,并不方便,二是现实生活中一般不会有人给你画个树形图来表明关系吧,那样不方便,大多数情况下都是用的关系表,比较简便明了)

现在假设,后端给前端的返回数据就是个关系表数组而不是树形对象,而前端要渲染页面需要用到这个树形对象(例如elementUi中的树组件),那么我们如何将这个关系表数组转化为树形对象呢?

因为我们每个树形图的每一层关系都是父子,如果我们可以定义一个函数,这个函数可以返回父节点的所有子节点,那就方便了

function getChildrenList(List,name){
    //list为关系表数组
    //name为要查询子节点的父节点名
    const res = []//定义name对应的所有子节点数组
    //循环关系表数组,找到子节点
    List.forEach(item=>{
        //如果遍历到的对象item的父节点就是name的话,说明item就是name的子节点
        if(item.parent === name){
            //将子节点放入res中
            res.push(item)
        }
    })
    //循环完成之后返回子节点数组
    return res
}
const result = getChildrenList(list,'曹操')
console.log(result)//[ { name: '曹植', parent: '曹操' }, { name: '曹丕', parent: '曹操' } ]

有了这个函数,我们可以查找到某个父节点下面的所有子节点,比如曹操的儿子是曹植和曹丕

 现在我们只能找到父节点的子节点,并不能找到父节点的孙子节点(也就是子节点的子节点),那么如何找子节点的子节点呢,显然,我们让子节点作为父节点,再次调用这个找子节点的函数,就可以找到子节点的子节点了,依次类推,不断回调,一直找下去,直到某个节点再没有子节点停止,如下图所示:

 代码如下:

function getChildrenList(List,name){
    //list为关系表数组
    //name为要查询子节点的父节点名
    const res = []//定义name对应的所有子节点数组
    //循环关系表数组,找到子节点
    List.forEach(item=>{
        //如果遍历到的对象item的父节点就是name的话,说明item就是name的子节点
        if(item.parent === name){
            //以item作为新的父节点,再次查找他的子节点
            item.children=getChildrenList(List,item.name)
            //将子节点放入res中
            res.push(item)
        }
    })
    //循环完成之后返回子节点数组
    return res
}
const result = getChildrenList(list,'曹操')
console.log(result)
// [
//     { name: '曹植', parent: '曹操', children: [ [Object], [Object] ] },
//     { name: '曹丕', parent: '曹操', children: [ [Object], [Object] ] }
// ]

例如:以曹操作为父节点,我们查找到了他的子节点和他的子节点的子节点(孙子节点),这是一个数组,最后我们将曹操作为根节点,将这个数组作为他的children,拼装起来,就可以返回一个家族关系的树形对象了

function getChildrenList(List,name){
    //list为关系表数组
    //name为要查询子节点的父节点名
    const res = []//定义name对应的所有子节点数组
    //循环关系表数组,找到子节点
    List.forEach(item=>{
        //如果遍历到的对象item的父节点就是name的话,说明item就是name的子节点
        if(item.parent === name){
            //以item作为新的父节点,再次查找他的子节点
            item.children=getChildrenList(List,item.name)
            //将子节点放入res中
            res.push(item)
        }
    })
    //循环完成之后拼装,形成树形对象
    return {
        name:name,
        children:res
    }
}
const result = getChildrenList(list,'曹操')
console.log(result)
// {
//     name: '曹操',
//     children: [
//       { name: '曹植', parent: '曹操', children: [Object] },
//       { name: '曹丕', parent: '曹操', children: [Object] }
//     ]
//   }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值