# 扁平数组&树形数组

扁平数组


const array = [
  { name: '一级', id: 1, pid: 0},
  { name: '一级子级1', id: 11, pid: 1},
  { name: '一级子级2', id: 12, pid: 1},
  { name: '二级', id: 2, pid: 0},
  { name: '二级子级1', id: 21, pid: 2},
  { name: '二级子级2', id: 22, pid: 2},
  { name: '三级', id: 3, pid: 0},
  { name: '三级子级1', id: 31, pid: 3},
  { name: '三级子级1', id: 32, pid: 3},
  { name: '三级子级1', id: 33, pid: 3},
  { name: '一1级子级1', id: 111, pid: 11},
  { name: '一1级子级2', id: 112, pid: 11},
  { name: '一1级子级3', id: 121, pid: 12},
  { name: '一1级子级4', id: 122, pid: 12},
  { name: '二1级子级1', id: 211, pid: 21},
  { name: '二1级子级2', id: 212, pid: 21},
  { name: '二1级子级3', id: 221, pid: 22},
  { name: '二1级子级4', id: 222, pid: 22},
  { name: '三1级子级1', id: 311, pid: 31},
  { name: '三1级子级2', id: 312, pid: 31},
  { name: '三1级子级3', id: 321, pid: 32},
  { name: '三1级子级4', id: 322, pid: 33},
];

树形数组


const treeArr = [
  { name: '一级', id: 1, children: [
    { name: '一级子级1', id: 11, children: [
      { name: '一1级子级1', id: 111, children: []},
      { name: '一1级子级2', id: 112, children: []}
    ]},
    { name: '一级子级2', id: 12, children: [
      { name: '一1级子级3', id: 121, children: []},
      { name: '一1级子级4', id: 122, children: []}
    ]},
  ]}, 
  { name: '二级', id: 2, children: [
    { name: '二级子级1', id: 21, children: [
      { name: '二1级子级1', id: 211, children: []},
      { name: '二1级子级2', id: 212, children: []}
    ]},
    { name: '二级子级2', id: 22, children: [
      { name: '二1级子级3', id: 221, children: []},
      { name: '二1级子级4', id: 222, children: []},
    ]},
  ]}, 
  { name: '三级', id: 3, children: [
    { name: '三级子级1', id: 31, children: [
      { name: '三1级子级1', id: 311, children: []},
      { name: '三1级子级2', id: 312, children: []},
    ]},
    { name: '三级子级1', id: 32, children: [
      { name: '三1级子级3', id: 321, children: []},
    ]},
    { name: '三级子级1', id: 33, children: [
      { name: '三1级子级4', id: 322, children: []},
    ]},
  ]}
];

扁平转树形

方法一:两层循环,时间复杂度O(n^2)


function arrToTree(arr) {
  if (!Array.isArray(arr)) {
    return;
  }
  arr.forEach(item => {
    arr.forEach(it => {
      if (it.pid === item.id) {
        !item.children && (item.children = [])
        item.children.push(it);
      }
    })
  });
  return arr.filter(item => item.pid === 0);
}

方法二:通过对象,找到父级,时间复杂度O(n)


function arrToTree(arr) {
  const obj = {};
  const target = [];
  arr.forEach(item => {
    obj[item.id] = item;
  });
  arr.forEach(item => {
    if (obj[item.pid]) {
      !obj[item.pid].children && (obj[item.pid].children = []);
      obj[item.pid].children.push(item);
    } else {
      target.push(item);
    }
  });
  return target;
}

TIP

核心都是利用的引用对象的特性,各自找到子节点,父子孙就自动连续起来了

树形转扁平


function treeToArr(tree, pid = 0) {
  const target = [];
  tree.forEach(item => {
    item.pid = pid;
    target.push(item);
    if (item.children) {
      target.push(...treeToArr(item.children, item.id));
      delete item.children
    }
  });
  return target;
}