遇到一个扁平数据结构转 Tree(树状结构)的问题

244 阅读2分钟

前言

前几天在网上看到一篇文章,说的是中高级前端必须会的几个技能和题目,里面刚好一个扁平数据结构转 Tree 的问题。

在前端开发时,这种问题我们会遇到的不多,大部分都是后端处理好之后再传给我们的,但是我们也要自己学会,并且掌握,毕竟我们也是有追求的嘛😏

废话不多说,直接上菜!

题目:

1、根据数组中的元素,每个元素的 pid 根节点,然后把它挂载到 id(父节点) 等于 pid(子节点)的元素 children 上

let arr = [ 
    {id: 1, name: '部门1', pid: 0}, 
    {id: 2, name: '部门2', pid: 1}, 
    {id: 3, name: '部门3', pid: 1}, 
    {id: 4, name: '部门4', pid: 3}, 
    {id: 5, name: '部门5', pid: 4}, 
]

2、希望得到的数据:

[
  {
    "id": 1,
    "name": "部门1",
    "pid": 0,
    "children": [
      {
        "id": 2,
        "name": "部门2",
        "pid": 1,
        "children": []
      },
      {
        "id": 3,
        "name": "部门3",
        "pid": 1,
        "children": [
          // 结果 ,,,
        ]
      }
    ]
  }
]

思路:

1、这个问题所考的是对 Tree、原型链、指针(类似)的理解,因为要变成树状结构,而且要将所有的元素放到 Tree 的节点上,并且输出根节点就能得到所有的节点

2、先把数组转成 Map 类型,然后将数组类的数据以键值对的方式放入,key 是 id,value 是对象,在 value 中再添加一个 children: [] 的属性

3、创建一个 空对象vObj,遍历 Map,去比对当前 对象 是否有 pid,不存在就是根节点,将它赋值给之前创建的 空对象vObj,存在则根据当前对象的 pid 获取 父元素的对象,并且把当前对象放到父元素对象中的children里面

4、最后 return 空对象vObj 即可

直接上代码

let arr = [
  { id: 3, name: '部门3', pid: 1 },
  { id: 1, name: '部门1', pid: 0 },
  { id: 2, name: '部门2', pid: 1 },
  { id: 5, name: '部门5', pid: 4 },
  { id: 4, name: '部门4', pid: 3 },
  { id: 9, name: '部门9', pid: 3 },
  { id: 7, name: '部门7', pid: 1 },
  { id: 8, name: '部门8', pid: 2 },
  { id: 6, name: '部门6', pid: 4 },
]
function deepTree(arr) {
  const vMap = new Map();
  arr.forEach(item => {
    vMap.set(item.id, Object.assign(item, { children: [] }));
  });
  let vObj = {};
  vMap.forEach(item => {
    if (vMap.has(item.pid)) {
      const vParent = vMap.get(item.pid);
      vParent.children.push(item);
    } else {
      vObj = vMap.get(item.id);
    }
  })
  return vObj
}

希望我的思路能给小伙伴们提供一些参考!