实现一个树结构与扁平化数组相互转换排序

70 阅读2分钟

前言

今天接了一个需求,产品想要一个扁平化数组可支持拖拽,更改标签实现树嵌套排序的功能。

要求

  • 1.树结构与扁平化数组需要可以互相转化
  • 2.支持扁平化数组排序、增加、删除、插入、替换
  • 3.支持树结构拖拽(利用el-tree的可拖拽)

树结构转扁平化数组

function flattenAndSort(treeData) {
  const flattenedData = [];

  // 定义递归函数
  const flattenRecursive = (node, parentId, index) => {
      // 生成当前节点的id
      const id = parentId ? `${parentId}-${index + 1}` : `${index + 1}`;

      // 添加当前节点到扁平化数组中
      flattenedData.push({ label: node.label, id });

      // 递归处理子节点
      if (node.children) {
          node.children.forEach((child, idx) => flattenRecursive(child, id, idx));
      }
  };

  // 遍历每个根节点
  treeData.forEach((root, index) => flattenRecursive(root, null, index));

  return flattenedData;
}

// 示例数据
const data = [
  {
      label: 'Level one 1',
      children: [
          {
              label: 'Level two 1-1',
              children: [
                  {
                      label: 'Level three 1-1-1',
                  },
              ],
          },
      ],
  },
  {
      label: 'Level one 2',
      children: [
          {
              label: 'Level two 2-1',
              children: [
                  {
                      label: 'Level three 2-1-1',
                  },
              ],
          },
          {
              label: 'Level two 2-2',
              children: [
                  {
                      label: 'Level three 2-2-1',
                  },
              ],
          },
      ],
  },
  {
      label: 'Level one 3',
      children: [
          {
              label: 'Level two 3-1',
              children: [
                  {
                      label: 'Level three 3-1-1',
                  },
              ],
          },
          {
              label: 'Level two 3-2',
              children: [
                  {
                      label: 'Level three 3-2-1',
                  },
              ],
          },
      ],
  }
];

// 调用函数扁平化数据
const flattenedData = flattenAndSort(data);
console.log(flattenedData);

扁平化数组转树结构

对扁平化数组处理

// 提取父节点
const flattenedData = [
    { label: 'Level one 1', id: '1' },
    { label: 'Level two 1-1', id: '1-1' },
    { label: 'Level three 1-1-1', id: '1-1-1' },
    { label: 'Level one 2', id: '2' },
    { label: 'Level two 2-1', id: '2-1' },
    { label: 'Level three 2-1-1', id: '2-1-1' },
    { label: 'Level two 2-2', id: '2-2' },
    { label: 'Level three 2-2-1', id: '2-2-1' },
    { label: 'Level one 3', id: '3' },
    { label: 'Level two 3-1', id: '3-1' },
    { label: 'Level three 3-1-1', id: '3-1-1' },
    { label: 'Level two 3-2', id: '3-2' },
    { label: 'Level three 3-2-1', id: '3-2-1' },
];



flattenedParent(flattenedData) {
  const transformedData = [];
  for (let i = 0; i < flattenedData.length; i++) {
    const current = flattenedData[i];
    transformedData.push({ ...current }); // Copy the current object

    // Get parent id from current id
    const parentId = getParentId(current.id);
    if (parentId !== null) {
        transformedData[i].parentId = parentId; // Add parentId to the current object in the new array
    }
}
return transformedData

function getParentId(childId) {
  const parts = childId.split('-');
  if (parts.length === 1) {
      // If there's no dash, it's a top-level node
      return null;
  } else {
      // Remove the last part to get the parent id
      parts.pop();
      return parts.join('-');
  }
}
}

console.log(flattenedParent(flattenedData));

扁平化数组转 树结构

// 扁平化转树
const flattenedData = [
    { label: 'Level one 1', id: '1' },
    { label: 'Level two 1-1', id: '1-1', parentId: '1' },
    { label: 'Level three 1-1-1', id: '1-1-1', parentId: '1-1' },
    { label: 'Level one 2', id: '2' },
    { label: 'Level two 2-1', id: '2-1', parentId: '2' },
    { label: 'Level three 2-1-1', id: '2-1-1', parentId: '2-1' },
    { label: 'Level two 2-2', id: '2-2', parentId: '2' },
    { label: 'Level three 2-2-1', id: '2-2-1', parentId: '2-2' },
    { label: 'Level one 3', id: '3' },
    { label: 'Level two 3-1', id: '3-1', parentId: '3' },
    { label: 'Level three 3-1-1', id: '3-1-1', parentId: '3-1' },
    { label: 'Level two 3-2', id: '3-2', parentId: '3' },
    { label: 'Level three 3-2-1', id: '3-2-1', parentId: '3-2' },
];

function unflattenTree(flattenedData) {
    const tree = [];

    const map = {}; // Create a map to store references to nodes by id

    flattenedData.forEach(node => {
        map[node.id] = { ...node, children: [] }; // Initialize each node with an empty children array
    });

    Object.values(map).forEach(node => {
        if (node.parentId) {
            // If node has a parentId, add it as a child of the parent node
            map[node.parentId].children.push(node);
        } else {
            // Otherwise, it's a root node, add it to the tree
            tree.push(node);
        }
    });

    return tree;
}

const treeData = unflattenTree(flattenedData);
console.log(treeData);