通俗易懂的tree与array转换算法

1,017 阅读2分钟

前言🖖

最近在管理端项目中遇到树型结构需要扁平化并且对扁平化数据处理完转换回树型结构的一个数据变动,经过理解与总结将解决方案记录一下

1.Tree转Array

实现思想:通过递归的方式合并数组,直到children为[]的时候停止递归。

// 待处理树型数据
const treeData = [
    {
        "id": 1,
        "title": "小叶同学1",
        "parent_id": 0
    },
    {
        "id": 2,
        "title": "小叶同学2",
        "parent_id": 0,
        "children": [
            {
                "id": 3,
                "title": "小叶同学2-1",
                "parent_id": 2,
                "children": [
                    {
                        "id": 4,
                        "title": "小叶同学3-1",
                        "parent_id": 3,
                        "children": [
                            {
                                "id": 5,
                                "title": "小叶同学4-1",
                                "parent_id": 4
                            }
                        ]
                    }
                ]
            },
            {
                "id": 6,
                "title": "小叶同学2-2",
                "parent_id": 2
            }
        ]
    }
]

// 扁平化方法
function treeToArray(data) {
  // 遍历数组
  return data.reduce((res,{children = [], ...params}) => {
    // 合并新数组并递归子数据
    return res.concat([params],treeToArray(children))
  },[])  
}
const arrayData = treeToArray(treeData)
console.log(arrayData)

输出结果:

[
  {id: 1, title: "小叶同学1", parent_id: 0},
  {id: 2, title: '小叶同学2', parent_id: 0},
  {id: 3, title: '小叶同学2-1', parent_id: 2},
  {id: 4, title: '小叶同学3-1', parent_id: 3},
  {id: 5, title: '小叶同学4-1', parent_id: 4},
  {id: 6, title: '小叶同学2-2', parent_id: 2},
]

2.Array转Tree

实现思想:

(1)通过存储一份(id=>数据)的对象便于子节点查找父节点位置

(2)将第一层节点推入新数组中,其子节点会因为父节点存储地址不会发生变化的原因自行连接。

(3)通过判断父节点是否存在数组中,并且将其推入相关的父节点。

let arrayData = [
  {id: 1, title: "小叶同学1", parent_id: 0},
  {id: 2, title: '小叶同学2', parent_id: 0},
  {id: 3, title: '小叶同学2-1', parent_id: 2},
  {id: 4, title: '小叶同学3-1', parent_id: 3},
  {id: 5, title: '小叶同学4-1', parent_id: 4},
  {id: 6, title: '小叶同学2-2', parent_id: 2},
]

function arrayToTree(list) {
  const res = []
  // 将parent_id抽离出来便于后期通过id查询对应数据
  const map = list.reduce((res,item) => (res[item.id] = item,res),{})
  for(item of list) {
    if(item.parent_id === 0) {
      res.push(item)
      continue;
    }
    // 判断父节点是否存在列表中
    if(item.parent_id in map) {
      // 获取父节点数据
      const parent = map[item.parent_id]
      // 判断父节点数据是否存在子任务,没有则进行初始化
      parent.children = parent.children || []
      // 将数据推入父节点中
      parent.children.push(item)
    }
  }
  return res
}

const treeData = arrayToTree(arrayData)
console.log(treeData)

输出结果:

[
    {
        "id": 1,
        "title": "小叶同学1",
        "parent_id": 0
    },
    {
        "id": 2,
        "title": "小叶同学2",
        "parent_id": 0,
        "children": [
            {
                "id": 3,
                "title": "小叶同学2-1",
                "parent_id": 2,
                "children": [
                    {
                        "id": 4,
                        "title": "小叶同学3-1",
                        "parent_id": 3,
                        "children": [
                            {
                                "id": 5,
                                "title": "小叶同学4-1",
                                "parent_id": 4
                            }
                        ]
                    }
                ]
            },
            {
                "id": 6,
                "title": "小叶同学2-2",
                "parent_id": 2
            }
        ]
    }
]