js树形结构操作

Array 转 树状结构

实现思路

  1. 按照pid分组,分组可以大大减少递归次数。。(Array分组的最好方式是用对象接收Array的项,该对象的key值就是分组凭证)
  2. 按照pid和id的匹配 递归 已分组的数据。

代码

/**
 * Array转树形结构的算法
 * @params list     代转化数组
 * @params parentId 起始节点(默认为'0')
 * @params pKey     父节点key值。默认pid
 * @params cKey     当前节点唯一标志。默认id
 */
export function getTrees(list, parentId = '0', pKey = 'pid', cKey = 'id') {
  let items = {}
  // 获取每个节点的直属子节点,*记住是直属,不是所有子节点
  for (let i = 0; i < list.length; i++) {
    let key = list[i][pKey]
    if (items[key]) {
      items[key].push(list[i])
    } else {
      items[key] = []
      items[key].push(list[i])
    }
  }
  return formatTree(items, parentId, cKey)
}

// 利用递归格式化每个节点
function formatTree(items, parentId, cKey) {
  let result = []
  if (!items[parentId]) {
    return result
  }
  for (let t of items[parentId]) {
    const temp = formatTree(items, t[cKey], cKey)
    if (temp.length > 0) {
      t.children = temp
    }
    result.push(t)
  }
  return result
}

根据节点值查找树形结构中的路径、子树

实现思路

  1. 使用深度优先算法,递归按照层级查找
  2. 找到指定节点,返回路径

代码

/**
 * 根据节点值查找树形结构中的路径
 * @param {String|Number} value 节点的值
 * @param {Array} tree 树形结构
 * @param {String} attr 匹配值的属性
 * @param {String} childAttr 匹配子节点数组的属性
 */
export function findTreePath(value, tree, attr = 'id', childAttr = 'children') {
  if (!(tree instanceof Array)) {
    console.error('tree: 请传入树形数组进行过滤!')
    return []
  }
  if (tree.length === 0) return []

  for (let i = 0; i < tree.length; i++) {
    const item = tree[i]

    if (item[attr] === value) {
      // 如果找到, 则跳出
      return [item[attr]]
    }
    if (item[childAttr]) {
      const path = findTreePath(value, item[childAttr], attr, childAttr)
      if (path.length > 0) {
        // 子节点找到, 把本节点插入到第一个
        path.splice(0, 0, item[attr])
        return path
      }
    }
  }
  return []
}

/**
 * 查找树的指定节点
 * @param {String|Number} value 节点的值
 * @param {Array} tree 树形结构
 * @param {String} attr 匹配值的属性
 * @param {String} childAttr 匹配子节点数组的属性
 */
export function findTreeNode(value, tree, attr = 'id', childAttr = 'children') {
  if (!(tree instanceof Array)) {
    console.error('tree: 请传入树形数组进行过滤!')
    return null
  }
  if (tree.length === 0) return

  for (let i = 0; i < tree.length; i++) {
    const item = tree[i]

    if (item[attr] === value) {
      // 如果找到, 则跳出
      return item
    }
    if (item[childAttr]) {
      const node = findTreeNode(value, item[childAttr], attr, childAttr)
      if (node) {
        // 找到即返回
        return node
      }
    }
  }

  return null
}
  • 10
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值