将Js对象转化为树状结构

实现效果

// 转换前:
source = [{
            id: 1,
            pid: 0,
            name: 'body'
          }, {
            id: 2,
            pid: 1,
            name: 'title'
          }, {
            id: 3,
            pid: 2,
            name: 'div'
          }]
// 转换为: 
tree = [{
          id: 1,
          pid: 0,
          name: 'body',
          children: [{
            id: 2,
            pid: 1,
            name: 'title',
            children: [{
              id: 3,
              pid: 1,
              name: 'div'
            }]
          }
        }]

思路分析

我们可以给这道题换个场景:
火车站,多个家庭混乱排列,一个父亲可能有多个孩子,每个人都知道自己的id和父亲的id(假设id唯一)以及自己的名字。
现在需要我们重新排列他们,复原家庭关系。
在实际生活中可以如何解决:

  1. 让所有人排好队,询问每一个人,你的pid是多少
  2. 如果他的pid为0,则说明他是父亲,我们直接将他放到另一边
  3. 如果他的pid不为0,则在大厅喊话:“谁的id是这个”
  4. 此时就会找到他的父亲,我们将这个儿子交给父亲
  5. 询问完所有的家庭,就完成了任务

提示:只是一个小案例,不要去纠结细节,ggg

代码实现

function jsonToTree (data) {
  if (!Array.isArray(data)) {
    return result
  }
  // 1. result为一个新的大厅,来存放已经组好队的家庭
  let result = []
  // 2.使用map,将当前对象的id与当前对象对应存储起来
  // PS:相当于我们在大厅喊话,只用一次就可以找到父亲,也就是O(1)
  let map = {}
  data.forEach(item => {
    map[item.id] = item
  })
  // 3.询问每一个人,它的父亲是谁
  data.forEach(item => {
    let parent = map[item.pid]
    console.log('打印的parent', parent)
    // 如果有父亲,就把父亲喊出来,把孩子交给父亲
    if (parent) {
      (parent.children || (parent.children = [])).push(item)
    }
    else {
    // 如果没有父亲,说明这个人就是父亲,直接把他带到排好序的大厅
      result.push(item)
    }

  })
  // 新的大厅为已经排好的家庭
  return result
}
console.log(jsonToTree(source))
posted @ 2022-10-24 09:19  含若飞  阅读(329)  评论(0编辑  收藏  举报