与一个方法将origin转化为tree,要求支持无限级和性能

将一个扁平的 origin 数据结构转换为树形结构,并且需要支持无限级和高性能,这在前端开发中是一个常见问题。 最佳方法取决于 origin 数据的具体格式和你的性能需求。 以下提供几种方法,并分析其优缺点:

方法一:递归方法 (简单易懂,但可能性能较差)

这种方法简单易懂,但对于大型数据集,递归的深度可能会导致栈溢出或性能问题。

function originToTree(origin, idKey = 'id', parentKey = 'parentId') {
  const tree = [];
  const map = {};

  // 创建一个map用于快速查找节点
  origin.forEach(item => {
    map[item[idKey]] = item;
  });

  origin.forEach(item => {
    if (!item[parentKey]) {
      tree.push(item);
    } else {
      const parent = map[item[parentKey]];
      if (parent) {
        parent.children = parent.children || [];
        parent.children.push(item);
      }
    }
  });

  return tree;
}


// 示例数据
const originData = [
  { id: 1, parentId: null, name: 'A' },
  { id: 2, parentId: 1, name: 'B' },
  { id: 3, parentId: 1, name: 'C' },
  { id: 4, parentId: 2, name: 'D' },
  { id: 5, parentId: 2, name: 'E' },
  { id: 6, parentId: null, name: 'F'}
];

const tree = originToTree(originData);
console.log(JSON.stringify(tree, null, 2));

方法二:迭代方法 (性能更好,避免栈溢出)

迭代方法避免了递归的栈溢出问题,通常性能更好,尤其是在处理大型数据集时。

function originToTreeIterative(origin, idKey = 'id', parentKey = 'parentId') {
  const tree = [];
  const map = {};

  origin.forEach(item => map[item[idKey]] = item);

  origin.forEach(item => {
    if (!item[parentKey]) {
      tree.push(item);
    }
  });

  for (let i = 0; i < tree.length; i++) {
    const node = tree[i];
    buildChildren(node, origin, map, idKey, parentKey);
  }

  return tree;
}

function buildChildren(node, origin, map, idKey, parentKey) {
  for (let i = 0; i < origin.length; i++) {
    const item = origin[i];
    if (item[parentKey] === node[idKey]) {
      node.children = node.children || [];
      node.children.push(item);
      buildChildren(item, origin, map, idKey, parentKey); //递归构建子节点
    }
  }
}

const treeIterative = originToTreeIterative(originData);
console.log(JSON.stringify(treeIterative, null, 2));

方法三:使用第三方库 (方便快捷,可能需要引入依赖)

一些前端库,例如 lodash,提供了树形结构相关的函数,可以简化代码,但需要引入额外的依赖。 这通常不是最优选择,除非你已经在使用该库。

性能优化建议:

  • 使用Map: Map 对象比 Array.find 或循环查找效率更高,尤其是在大型数据集的情况下。 如上例所示,我们使用 Map 来快速查找父节点。
  • 优化数据结构: 如果可能,预处理 origin 数据,例如按 parentId 排序,可以进一步提高性能。
  • 避免不必要的循环: 仔细检查代码,避免重复遍历数据。
  • 分治法 (对于极端大型数据集): 如果数据量非常大,可以考虑分治法,将数据分成更小的块,分别处理后再合并结果。

选择哪种方法取决于你的具体需求和数据量。 对于小型到中等规模的数据集,递归方法足够简单易懂。 对于大型数据集,迭代方法通常性能更好,并且避免了栈溢出的风险。 记住始终测试和分析你的代码性能,以确保它满足你的需求。 如果性能仍然是一个问题,则需要考虑更高级的

posted @ 2024-12-14 09:17  王铁柱6  阅读(47)  评论(0)    收藏  举报