数组转化成树

166 阅读3分钟

数组转化成树(难点-难点-难点)

data = 
[
  {id:"01", name: "张大大", pid:"", job: "项目经理"},
  {id:"02", name: "小亮", pid:"01", job: "产品leader"},
  {id:"03", name: "小美", pid:"01", job: "UIleader"},
  {id:"04", name: "老马", pid:"01", job: "技术leader"},
  {id:"05", name: "老王", pid:"01", job: "测试leader"},
  {id:"06", name: "老李", pid:"01", job: "运维leader"},
  {id:"07", name: "小丽", pid:"02", job: "产品经理"},
  {id:"08", name: "大光", pid:"02", job: "产品经理"},
  {id:"09", name: "小高", pid:"03", job: "UI设计师"},
  {id:"10", name: "小刘", pid:"04", job: "前端工程师"},
  {id:"11", name: "小华", pid:"04", job: "后端工程师"},
  {id:"12", name: "小李", pid:"04", job: "后端工程师"},
  {id:"13", name: "小赵", pid:"05", job: "测试工程师"},
  {id:"14", name: "小强", pid:"05", job: "测试工程师"},
  {id:"15", name: "小涛", pid:"06", job: "运维工程师"}
]

 目标:
const treeData = arrToTree(data)
 treeData就是:
 [{   label: '张大大',  children: [    {      label: '小亮',      children: [{label: '小丽'},{label: '大光'}]
    },
    {
      label: '小美',
      children: [{label: '小高'}]
     },
     {
       label: '老马',
       children: [{label: '小刘'},{label: '小华'},{label: '小李'}]
     },
     {
       label: '老王',
       children: [{label: '小赵'},{label: '小强'}]
     },
     {
       label: '老李',
       children: [{label: '小涛'}]
     }
   ]
 }]

//总方法
function arrToTree(data) {
  let arr = []
  data.forEach(item => {
    if (!item.pid) {
      // 如果id为空,则放在根节点下
      arr.push({
        label: item.name,
        id: item.id
      })
    } else {
      // 如果id不为空,则执行【对象插入树算法】
      buildTree(arr, item)
    }
  })
  // 执行【清除id算法】以清除构建数据过程中临时创建的id属性,并返回数据
  return removeId(arr)
}
 
// 【对象插入树算法】
function buildTree(arr, obj) {
  arr.forEach(item => {
    if (obj.pid === item.id) {
      // 先比较item是否是obj的上级
      if (!item.children) {
        item.children = []
      }
      item.children.push({
        label: obj.name,
        id: obj.id
      })
    } else if (item.children) {
      // 如果item不是obj的上级,且item有孩子,那查看孩子是不是obj的上级(递归)
      buildTree(item.children, obj)
    }
  })
}
 
// 【清除id算法】
function removeId(arr) {
  arr.forEach(item => {
    // 删除item的id
    delete item.id
    if (item.children) {
      // 如果item有孩子,删除item孩子的id(递归)
      removeId(item.children)
    }
  })
  return arr
}
 
//打印查看结果
console.log(arrToTree(data))

/**
 * 把平铺的数组结构转成树形结构
 *
 * [
 *  {id:"01", pid:"",   "name":"老王" },
 *  {id:"02", pid:"01", "name":"小张" }
 * ]
 * 上面的结构说明: 老王是小张的上级
 */
export function tranListToTreeData(item) {
  // 最重要产出的数据结构
  const newList = []
  // 把item的每一项都用对象存储起来,因为要给每一项增加一个id指向   方便之后往里头添加东西,先把空盒子搭起来21行填东西
  const everyitem = {}
  // 建立映射关系,通过id快速找到对应的元素
  item.forEach(element => {
    if (!element.children) {
      element.children = []
    }
    //
    everyitem[element.id] = element
    //   "312c": { 'id': '312c', 'pid': '',     'name': '财务部',    children: [{ 'id': '312d', 'pid': '312c', 'name': '财务核算部',children: []}] },
    //   "312d": { 'id': '312d', 'pid': '312c', 'name': '财务核算部',children: []}
    // }
    element.forEach(ite => {
      // 现在对于每一个元素来说  先找到他的上级 如果能找到 说明有上级 并把它添加到上级的children中  如果找不到   说明他没有上级   直接添加到 最终的数据结构中
      const parent = everyitem[ite.pid]
      if (parent) {
        parent.children.push(ite)
      } else {
        newList.push(ite)
      }
    })
    return newList
  })
}

// 两个小练习

将

`[ { label: '男', value: 0 }, { label: '女', value: 1 } ]`

转换成

`{0: '男', 1:'女'}`
const arr = [
  { label: '男', value: 0 },
  { label: '女', value: 1 }
]
function f1(arr) {
  return arr.reduce((obj, cur) => {
    obj[cur.value] = cur.label
    return obj
  }, {})
}
function f2(arr) {
  let obj = {}
  arr.forEach(item => {
    obj[item.value] = item.label
  })
  return obj
}
const obj1 = f1(arr) // obj ===> {0: '男', 1:'女'}
const obj2 = f2(arr) // obj ===> {0: '男', 1:'女'}
console.log(obj1)
console.log(obj2)


将

`{ 0: '男', 1:'女'}`

转换成

`[{label: '男', value: 0},{label: '女', value: 1}]`
const obj = { 0: '男', 1:'女'}
function f(obj) {
  let arr = []
  for (const key in obj) {
    arr.push({
      label: obj[key],
      value: key
    })
  }
  return arr
}
const arr = f(obj) // arr ===>  [{label: '男', value: 0},{label: '女', value: 1}]
console.log(arr)