js中扁平数据结构和树形结构的互相转换

442 阅读1分钟

树形结构扁平化

话不多说,上代码!

先定义一个树形结构

const treeArray = [
  {
    id: 1,
    pid: null,
    name: "p0",
    children: [
      {
        id: 2,
        pid: 1,
        name: "p1",
        children: [
          {
            id: 3,
            pid: 2,
            name: "p11",
            children: [],
          },
          {
            id: 4,
            pid: 2,
            name: "p12",
            children: [
              {
                id: 5,
                pid: 4,
                name: "p121",
                children: [
                  {
                    id: 6,
                    pid: 5,
                    name: "p1211",
                    children: [],
                  },
                ],
              },
            ],
          },
        ],
      },
      {
        id: 7,
        pid: 1,
        name: "p2",
        children: [
          {
            id: 8,
            pid: 7,
            name: "p21",
            children: [],
          },
        ],
      },
    ],
  },
];

第一种方法用递归

function treeToFlat1(tree: any) {
  let flat: any = [];
  for (const item of tree) {
    const { children, ...i } = item;
    if (children && children.length) {
      flat = flat.concat(treeToFlat1(children));
    }
    flat.push(i);
  }
  return flat;
}
console.log(treeToFlat1(treeArray));

第二种用reduce+递归,更简洁些

function treeToFlat2(tree: any) {
  return tree.reduce((result: any, item: any) => {
    const { children, ...i } = item;
    return result.concat(
      i,
      children && children.length ? treeToFlat2(children) : []
    );
  }, []);
}
console.log(treeToFlat2(treeArray));

将扁平化的数据转化成树

定义一个扁平化后的数据

const flatArray = [
  { id: 1, pid: null, name: "p0" },
  { id: 2, pid: 1, name: "p1" },
  { id: 3, pid: 2, name: "p11" },
  { id: 4, pid: 2, name: "p12" },
  { id: 5, pid: 4, name: "p121" },
  { id: 6, pid: 5, name: "p1211" },
  { id: 7, pid: 1, name: "p2" },
  { id: 8, pid: 7, name: "p21" },
];

第一种用递归实现

function flatToTree1(flat: any) {
  let tree: any = [];
  let getChildren = (result: any, pid: any) => {
    flat.map((item: any) => {
      if (item.pid === pid) {
        let son = { ...item, children: [] };
        result.push(son);
        getChildren(son.children, son.id);
      }
    });
  };
  getChildren(tree, null);
  return tree;
}
console.log(flatToTree1(flatArray));

第二种用嵌套filter实现

function flatToTree2(flats: any) {
  let flat = JSON.parse(JSON.stringify(flats));
  return flat.filter((parent: any) => {
    let son = flat.filter((child: any) => {
      return parent.id === child.pid;
    });
    son.length > 0 ? (parent.children = son) : (parent.children = []);
    return parent.pid === null;
  });
}
 console.log(flatToTree2(flatArray));

第三种利用map对象实现

function flatToTree3(flat: any) {
  let map: any = {};
  flat.forEach((item: any) => {
    item.children = [];
    map[item.id] = item;
  });
  let tree: any = [];
  flat.forEach((item: any) => {
    if (item.pid) {
      let parent = map[item.pid];
      parent.children.push(item);
    } else {
      tree.push(item);
    }
  });
  return tree;
}
console.log(flatToTree3(flatArray));

三种方式结果都一样,只是时间复杂度上有区别。