[算法解腻]-数组转树

160 阅读1分钟

6ece4aa4-57a4-4f84-8c41-293f77d07ef1.png

作者: 云峰 github: github.com/ihtml5

一、背景

数组转树是指通过一个数组结构生成一个树形结构。日常我们看到的菜单就是这类数据结构的应用,后台下发的数据一般是拍平后的数组,通过数组中的parentId和id之间的关系来建立树形结构。

二、数据示例

const nodes = [
{ id: 3, name: "节点C", parentId: 1 },
{ id: 6, name: "节点F", parentId: 3 },
{ id: 0, name: "root", parentId: null },
{ id: 1, name: "节点A", parentId: 0 },
{ id: 8, name: "节点H", parentId: 4 },
{ id: 4, name: "节点D", parentId: 1 },
{ id: 2, name: "节点B", parentId: 0 },
{ id: 5, name: "节点E", parentId: 2 },
{ id: 7, name: "节点G", parentId: 2 },
{ id: 9, name: "节点I", parentId: 5 }
];

三、递归法

思路

从根节点出发,逐层进行递归 root -> 1 -> 2

const arrayToTree = (nodes, parentId) => {
  const list = nodes.filter(node => node.parentId === parentId);
  
  if (list.length === 0) {
    return [];
  }
  
  return list.map(item => ({
    ...item,
    children: arrayToTree(nodes, item.id),
  }));
};

四、对象引用

const convert = (nodes) => {
  const tree = [];
  let map = {}; 
  nodes.forEach(node => {
    if (!Array.isArray(node.children)) {
      node.children = [];
    }
    
    map[node.id] = node;
  });
   nodes.forEach(node => {
    const parent = map[node.parentId] || null;
    if (parent !== null) {
       parent.children.push(node);
    } else {
       tree.push(node);
    }
  });
  map = null;
  return tree;
};