js根据id查找tree中的节点和路径

给定一棵树(一个对象),然后根据传入的id查找,经常遇到有两种情况:
1)查找是否有对应的节点,有则返回该节点;
2)记录对应树节点的路径。

树的结构如下:

let tree = {
  id: 1,
  name: "company",
  children: [
    {
      id: 2,
      name: "group1",
      children: [
        {
          id: 3,
          name: 'dept1'
        },
        {
          id: 5,
          name: 'dept2',
          children: [
            {
              id: 6,
              name: 'user1'
            }
          ]
        },
      ]
    },
    {
      id: 4,
      name: "gropu2"
    },
  ]
}

1、根据id查询tree上是否有该节点,有则返回

// 方法1: 利用递归,需要注意区分子节点是对象还是数组
let result = null // 报错最终结果
function findNodeFromTreeById(root, id) {
 if (!!root) {
   let type = Object.prototype.toString.call(root).slice(8, -1)
   if (type === 'Object') {
     if (root.id && root.id === id) {
       result = root
     } else {
       let node = root.children || null
       findNodeFromTreeById(node, id)
     }
   } else if (type === 'Array') {
     let needNode = root.find(x => !!x === true && x.id === id)
     if (!!needNode) {
       result = needNode
     } else {
       root && root.forEach(item => {
         if (item && item.children && item.children.length) {
           findNodeFromTreeById(item.children, id)
         }
       })
     }
   }
 }
 return result
}
// test
getNodeById(testTree, 4) // {id: 4, name: 'group2'}
findFromTreeById(testTree, 5) // {id: 5, name: 'dept2', children: [{id: 6, name: 'user1'}]}


// 方法2: 将tree变成一个数组
function getNodeById(tree, id) {
  let arr = Array.isArray(tree) ? tree : [tree]
  let result = null
  while (arr.length) {
    let item = arr.pop()
    if (item && item.id === id) {
      result = item
      break
    } else if (item && item.children && item.children.length) {
      arr.push(...item.children)
    }
  }
  return result
}

// test
getNodeById(tree, 4)) // { id: 4, name: 'group2' }
getNodeById(tree, 7)) // null

2、根据id查找tree中对应节点路径

// 利用递归,将tree转化成数组结构来操作
function getPathById(tree, id, path) {
  tree = Array.isArray(tree) ? tree : [tree]
  if (!path) {
    path = []
  }
  for (let i = 0, len = tree.length; i < len; i++) {
    let tempPath = [...path]
    tempPath.push(tree[i].name)
    if (tree[i].id === id) {
      return tempPath
    }
    if (tree[i].children) {
      return getPathById(tree[i].children, id, tempPath)
    }
  }
}

// test
getPathById(tree, 3) // ['company', 'group1', 'dept1']
getPathById(tree, 8) // null
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

英子的搬砖日志

您的鼓励是我创作的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值