数组转树
我们可以先对数组进行一个遍历,并且在遍历的过程中找出根节点,并且通过pid将有着父子关系的节点进行映射。后续为树的节点添加子节点会更快速。
function arrToTree(arr,rootId){
if(!Array.isArray(arr)) throw new Error('arr is not an Array')
let root = null
const pMap = new Map()
// 完成pid映射
arr.forEach(item=>{
const { id , name , pid} = item
if(pMap.has(pid)){
const children = pMap.get(pid)
children.push({id,name})
pMap.set(pid,children)
}else{
pMap.set(pid,[{id,name}])
}
if(id==rootId){
root = {
id,
name,
children:[]
}
}
})
appedChildren(root,pMap.get(root.id))
function appedChildren(curNode,children){
if(!Array.isArray(children)) return
if(!curNode.children) curNode.children = []
children.forEach(child=>{
if(pMap.has(child.id)){
// 有孩子
appedChildren(child,pMap.get(child.id))
}
curNode.children.push(child)
})
}
return root
}
树转数组(广度优先)
广度优先遍历由于是按照层级来的,所以我们可以采用队列的方式,当节点出队列的时候,把它的子节点进行入队,此时就可以保证顺序。
function treeToArr(root){
const queue = []
queue.unshift(root)
const list = []
while(queue.length){
const curNode = queue.pop()
list.push({id:curNode.id,name:curNode.name})
const children = curNode.children
if(children&&children.length){
children.forEach(child=>{
queue.unshift(child)
})
}
}
return list
}
找所有父级(树形)
因为如果到达叶子节点还不是目标id,则说明不在这个树上,则needChild是null,同理其不在目标节点数上的那条线needChild都是null
function findNodeParentTree(root,nodeId){
let rstRoot = null
const curNode = root
if(curNode.id == nodeId){
curNode.children ? delete curNode.children : ''
rstRoot = curNode
}else{
const children = curNode.children
if(children&&children.length){
let needChild = null
children.some(child=>{
needChild = findNodeParent(child,nodeId)
//因为如果到达叶子节点还不是目标id,则说明不在这个树上,则needChild是null,同理其不在目标节点数上的那条线needChild都是null
if(needChild) return true
})
if(needChild){
rstRoot = {
id:curNode.id,
name:curNode.name,
children: [ needChild ]
}
}
}
}
return rstRoot
}
找所有父级(数组)
和上一个思想一样,只是此处是利用数组收集,则可以使用concat进行数组合并。
function getParents(list,id){
for(let i in list){
if(list[i].id === id){
return [{ id:list[i].id , name:list[i].name }]
}
if(list[i].children && list[i].children.length > 0){
let result = getParents(list[i].children,id);
if(result){
return result.concat({ id:list[i].id , name:list[i].name })
}
}
}
}