数组转树形结构 和 树形结构转数组

引言

相信在面试的小伙伴,可能遇到关于数组转树形结构或者树形结构转数组的面试题,如果之前没有对算法题有所研究的小伙伴,初次遇到这个面试题的小伙伴可能有点懵。下面就由我带你轻松掌握关于它以及他的使用场景。

数组转树形的用途

为什么面试的时候会问关于它呢,其实这种树形结构的数据在项目中还是很常见的。树形结构的数据的主要用途就是供菜单渲染使用。不过这种数据的返回一般是由后端人员完成的,也不排除由前端人员转换的情况。

前端转换的场景:当我们拿到用户角色对应的菜单权限数组时,像:[home,goods,goodsmanage,chart,line] ,还拿到了整个菜单的数组列表,我们需要根据用户的权限来动态渲染出对应的菜单,此时我们应该如何处理呢?

1.根据整个菜单的数组列表和权限数组,生成该用户对应的菜单列表

2.把菜单列表转化为树形结构对象

3.根据树形结构对象渲染对应的菜单

数组转树形

现有后台返回的用户信息和完整菜单数组数据如下:
完整菜单数组

const list=[
{id:"0",pid:"",title:"菜单",key:'menu'},
{id:"1",pid:"0",title:"首页",key:'home'},
{id:"2",pid:"0",title:"商品",key:'goods'},
{id:"2-1",pid:"2",title:'商品管理',key:'goodsmanage'},
{id:"2-2",pid:'2',title:'商品分类',key:'goodscategory'},
{id:"3",pid:"0",title:"图表管理",key:'chart'},
{id:"3-1",pid:'3',title:"饼图",key:'pie'},
{id:"3-2",pid:'3',title:"条形图",key:'bar'},
{id:"3-3",pid:'3',title:"折线图",key:'line'}
]

用户信息

const user={
    name:'xxx',
    role:'xx'
    auth:['home','goods','goodsmanage','goodscategory','chart','pie']
}

1.先找到该角色对应的菜单列表

const myList=[]     // 定义该用户对应的菜单列表

for(let i of list)
{
    // 如果找到用户对应的菜单项,把该菜单项加进去
    if(user.auth.indexOf(i.key)!==-1)   myList.push(i)
}

2.开始转树形
方法一:非递归思路
非递归思路:找到自己的还是,然后把根节点返回出去。因为根节点会收纳自己的孩子,根节点的孩子也会收纳自己的孩子,以此类推。因此我们只需要找到根节点就相当于找到整颗树形了

function createTree(arr=[]){
	let res
	for(let i of arr){
		for(let j of arr){
			if(!i.pid) res=i    // 找到根节点
			if(i.id==j.pid)     // 让每个节点都去去寻找自己的子节点,然后将子节点收入其中
			{
			  if(!i.children)i.children=[]
			  i.children.push(j)
			}  
		}
	}
	return res
}
const myTree=createTree(myList)
console.log(myTree)

方法二:递归思路
找到自己的孩子,然后把根节点返回出去。让根节点找自己的子节点,然后递归子节点,让他们也去找自己的子节点,时间复杂度也是n的平方

function creatTree(arr=[],id){
let res,children=[]
arr.forEach(v=>{
  if(id==v.id) {
    v.children=children
    res=v
  } 
  if(v.pid==id) children.push(v)
  children.forEach(v=>{creatTree(arr,v.id)})
})
return res
}
const myTree=createTree(list,"0")   // 0是根节点的id
console.log(myTree)

3.渲染菜单,以antdMenu组件为例。

import {PureComponent} from "react"
import {Menu} from 'antd'

class index extends PureComponent{

	
linkto=(i)=>{
this.props.history.push(`${this.props.match.path}/${i.keyPath.reverse().join('/')}`)
}
	
render() {
	
	return (
	<div className='leftnav'>
	<Menu
	defaultSelectedKeys={keys}
	defaultOpenKeys={keys}
	mode="inline"
	theme="dark"
	items={this.state.myTree.children}    {/*这里的myTree就是上面的树形数据*/
	onClick={this.linkto}
	/>
	
	</div>
	)
	}
}
export default index

树形转数组

其实树形结构转数组涉及到了数据结构关于树的算法,例:先序遍历、中序遍历、后序遍历、层序遍历,区别就在于节点输出的顺序不一致。如果想了解关于树的这些算法,可以看看我发布的一篇文章——>js实现树的前、中、后、层序遍历

function treeToList(obj={}){
	const res=[]
  function a(obj={}){
	res.push({id:obj.id,pid:obj.pid})
	if(obj.children){
		for(let v of obj.children){
		 a(v)
		}
	}
	}
	a(obj)
	return res
}
const list=treeToList(myTree)
console.log(list)

结尾

感谢你的观看,希望这篇文章能给你带来快乐。如果有小伙伴有一些问题或者疑惑,欢迎提出和分享。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值