• 面试题——数组转树结构


          树结构大家应该都比较熟悉,这里我主要说两种:一个根节点和多个根节点。一个根节点,就像我们的html节点,不可能有和它同级的;多个根节点,比如我们的一二级导航栏。下面一个个分析:

    一个根节点

    初级 - 只能是两层树

    let arr = [
      {
        menuId: 1,
        name: '系统1',
        parentMenu: null
      },
      {
        menuId: 2,
        name: '系统1_0',
        parentMenu: 1
      },
      {
        menuId: 3,
        name: '系统1_1',
        parentMenu: 1
      }
    ]
    
    function turnToTreeOfOneRoot(arr) {
      if (!Array.isArray(arr)) {
        throw new Error('is not array')
      } else {
        return arr.reduce((cur, item) => {
          if (item.parentMenu == null) {
            cur = { children: [], ...item }
          } else if (item.parentMenu == cur.menuId) {
            cur.children.push(item)
          }
    
          return cur
        }, {})
      }
    }
    
    turnToTreeOfOneRoot(arr)
    

    升级 - 随便几层

    var arr1 = [
      {
        menuId: 1,
        name: '系统管理1',
        parentMenu: null
      },
      {
        menuId: 2,
        name: '系统管理1_0',
        parentMenu: 1
      },
      {
        menuId: 3,
        name: '系统管理1_1',
        parentMenu: 1
      },
      {
        menuId: 4,
        name: '系统管理2_0',
        parentMenu: 2
      }
    ]
    
    function turnToTreeOfOneRootPlus(arr) {
      var obj = {}
      arr.forEach(item => {
        if (item.parentMenu == null) {
          obj = item
        }
      })
    
      return arr.reduce((h, m) => {
        // 如果不是根节点
        if (m.parentMenu) {
          foo(h, m)
        }
    
        // 在obj里面为cur找到归宿
        function foo(obj, cur) {
          if (obj.menuId === cur.parentMenu) {
            if (!obj.children) {
              obj.children = []
            }
            obj.children.push(cur)
          } else if (obj.children) {
            obj.children.forEach(item => {
              foo(item, cur)
            })
          }
        }
    
        return h
      }, obj)
    }
    
    turnToTreeOfOneRootPlus(arr1)
    

    多个根节点

    初级 - 只能是两层树

    let arr2 = [
      {
        menuId: 1,
        name: '系统1',
        parentMenu: null
      },
      {
        menuId: 2,
        name: '系统1_0',
        parentMenu: 1
      },
      {
        menuId: 3,
        name: '系统1_1',
        parentMenu: 1
      },
      {
        menuId: 4,
        name: '系统2',
        parentMenu: null
      },
      {
        menuId: 5,
        name: '系统4_0',
        parentMenu: 4
      }
    ]
    
    function turnToTreeOfManyRoot(arr) {
      if (!Array.isArray(arr)) {
        throw new Error('is not array')
      } else {
        var roots = []
        arr.forEach(item => {
          if (item.parentMenu == null) {
            item.children = []
            roots.push(item)
          }
        })
    
        return arr.reduce((roots, cur) => {
          roots.forEach(item => {
            // 如果是根节点
            if (item.menuId == cur.parentMenu) {
              item.children.push(cur)
            }
          })
    
          return roots
        }, roots)
      }
    }
    
    turnToTreeOfManyRoot(arr2)
    

    升级 - 随便几层

    var arr3 = [
      {
        menuId: 1,
        name: '系统管理1',
        parentMenu: null
      },
      {
        menuId: 2,
        name: '系统管理2',
        parentMenu: null
      },
      {
        menuId: 3,
        name: '系统管理1_0',
        parentMenu: 1
      },
      {
        menuId: 4,
        name: '系统管理1_1',
        parentMenu: 1
      },
      {
        menuId: 5,
        name: '系统管理2_0',
        parentMenu: 2
      },
      {
        menuId: 6,
        name: '系统管理5_0',
        parentMenu: 5
      },
      {
        menuId: 7,
        name: '系统管理3',
        parentMenu: null
      }
    ]
    
    function turnToTreeOfManyRootPlus(arr) {
      var arrs = []
      arr.forEach(item => {
        if (!item.parentMenu) {
          arrs.push(item)
        }
      })
    
      return arr.reduce((h, m) => {
        if (m.parentMenu) {
          foo(h, m)
        }
    
        function foo(arr, cur) {
          arr.forEach(item => {
            if (item.menuId === cur.parentMenu) {
              if (!item.children) {
                item.children = []
              }
              item.children.push(cur)
            } else if (item.children) {
              foo(item.children, cur)
            }
          })
        }
    
        return h
      }, arrs)
    }
    
    turnToTreeOfManyRootPlus(arr3)
    

    ps:最后提醒一下,数组里面的对象一定是排序过的,也就是说父级一定在前面,它的子级一定在后面。比如:

    let arr = [
      {
        menuId: 1,
        name: '系统1',
        parentMenu: null
      },
      {
        menuId: 4,
        name: '系统2_0',
        parentMenu: 2
      },
      {
        menuId: 2,
        name: '系统1_0',
        parentMenu: 1
      },
      {
        menuId: 3,
        name: '系统1_1',
        parentMenu: 1
      }
    ]
    

    这样的数组,会导致menuId: 4丢失。因为它的父级在后面,所以遍历到它时没办法塞给它的父级。谨记:一定要排好序,然后进行数组遍历

  • 相关阅读:
    Android核心分析之二十五Android GDI之共享缓冲区机制
    Android核心分析之二十四Android GDI之显示缓冲管理
    Android核心分析之二十三Andoird GDI之基本原理及其总体框架
    Android核心分析之二十二Android应用框架之Activity
    Android核心分析之二十一Android应用框架之AndroidApplication
    Android核心分析之二十Android应用程序框架之无边界设计意图
    Android核心分析之十九电话系统之GSMCallTacker
    Android核心分析之十八Android电话系统之RIL-Java
    NFS 服务器的配置
    tftp 服务器的配置
  • 原文地址:https://www.cnblogs.com/chenwenhao/p/11146760.html
Copyright © 2020-2023  润新知