JS树结构操作:查找、遍历、筛选、树结构和列表结构相互转换

265 阅读1分钟
/**
 *性能最优
 * @param items
 * @returns
 */
export function arrayToTree(items: Array<any>) {
  const res = [] // 存放结果集
  const map: any = {}
  // 判断对象是否有某个属性
  const getHasOwnProperty = (obj: any, property: any) => Object.prototype.hasOwnProperty.call(obj, property)

  // 边做map存储,边找对应关系
  for (const i of items) {
    map[i.id] = {
      ...i,
      children: getHasOwnProperty(map, i.id) ? map[i.id].children : []
    }
    const newItem = map[i.id]
    if (i.pid === 0) {
      res.push(newItem)
    } else {
      if (!getHasOwnProperty(map, i.pid)) {
        map[i.pid] = {
          children: []
        }
      }
      map[i.pid].children.push(newItem)
    }
  }
  return res
}
/**
 * @description 查找包含自身节点的父代节点
 * @param tree 需要查找的树数据
 * @param curKey 当前节点key
 * @param keyField 自定义 key 字段
 * @param node 找到的node 可以不传
 */
export function findCurNode(tree: any, curKey: any, keyField: any) {
  let node
  tree.forEach((item: any) => {
    if (item[keyField] === curKey) {
      node = item
    }
    if (item.children && item.children.length) {
      const findChildren = findCurNode(item.children, curKey, keyField)
      if (findChildren) {
        node = findChildren
      }
    }
  })
  return node
}

/**
 * 时间复杂度为O(2n),需要一个Map把数据存储起来,空间复杂度O(n)
 * @param items
 * @returns
 */
export function arrayToTree2(items: Array<any>) {
  const res = [] // 存放结果集
  const map: any = {}

  // 先转成map存储
  for (const i of items) {
    map[i.id] = { ...i, children: [] }
  }

  for (const i of items) {
    const newItem = map[i.id]
    if (i.pid === 0) {
      res.push(newItem)
    } else if (Object.prototype.hasOwnProperty.call(map, i.pid)) {
      map[i.pid].children.push(newItem)
    }
  }
  return res
}
/**
 * 时间复杂度为O(2^n)。性能消耗很大。
 * @param items
 * @returns
 */
export function arrayToTree3(items: Array<any>) {
  const res: any = []
  const getChildren = (item: any, pid: number) => {
    for (const i of items) {
      if (i.pid === pid) {
        const newItem = { ...i, children: [] }
        item.push(newItem)
        getChildren(newItem.children, newItem.id)
      }
    }
  }
  getChildren(res, 0)
  return res
}
/**
 *树结构转化为列表结构
 * @param tree
 * @returns
 */
export function treeToArray(tree: Array<any>) {
  let res: any = []
  for (const item of tree) {
    const { children, ...i } = item
    if (children && children.length) {
      res = res.concat(treeToArray(children))
    }
    res.push(i)
  }
  return res
}

参考文献: 1,juejin.cn/post/689926…