首页 > 解决方案 > Javascript - 寻找一种转换父子关系的方法

问题描述

我在转换父子关系时遇到问题。截至目前,我的数据结构如下所示。

{
    "id": 7,
    "name": "Folder 1",
    "parent_folder": null,
    "folders": [
        {
            "id": 8,
            "name": "Folder 1-1",
            "parent_folder": 7
        },
        {
            "id": 10,
            "name": "Folder 1-2",
            "parent_folder": 7
        }
    ],
},
{
    "id": 8,
    "name": "Folder 1-1",
    "parent_folder": 7,
    "folders": [
        {
            "id": 9,
            "name": "Folder 1-1-1",
            "parent_folder": 8
        }
    ],
},
{
    "id": 9,
    "name": "Folder 1-1-1",
    "parent_folder": 8,
}

每个文件夹都有自己的表示,您可以在其中找到 parent_folder id 及其子项(仅向下一层)。

复杂性是当我尝试更深入地了解结构时。我可以创建如下结构:

Folder 1
    Folder 1-1
    Folder 1-2

但是当我尝试添加文件夹 1-1-1时,它让我失败了。

我想出的解决方案可以在下面找到。我从 API 端点获取此文件夹数据,并尝试仅处理该响应。检索到响应后,代码片段就出现了:

var tempFolderList = [];


var f = response.data.folders;

for (var folder in f) {
  if (f[folder].parent_folder) {
    console.log("PARENT TEMPLATE FOLDER FOUND");

    // Create temporary variable
    var tempChildFolder = {
      id: f[folder].id,
      name: f[folder].name,
      parent_folder: f[folder].parent_folder,
      children: [],
    };

    var attv = this.addToTree(tempFolderList, folder, tempChildFolder, f)
    console.log("attv: " + attv)

    if (attv) {
      this.tempFolderList = attv
    }
    else {
      tempFolderList.push(tempChildFolder)
    }

    // Check if id from current iteration is in temp Folder list
    // if yes add to the list, if not :TODO:
    // if (
    //   tempFolderList.find(
    //     (x) => x.id === f[folder].parent_folder
    //   )
    // ) {
    //   tempFolderList
    //     .find((x) => x.id === f[folder].parent_folder)
    //     .children.push(tempChildFolder);
    // }
  } else {
    // If folder do not have parent folder, just add to temp folder list
    var tempFolder = {
      id: f[folder].id,
      name: f[folder].name,
      parent_folder: f[folder].parent_folder,
      children: [],
    };
    tempFolderList.push(tempFolder);
  }
    console.log(tempFolderList);
}

这是 addToTree 函数:

addToTree(tempFolderList, folder, tempChildFolder, folderList) {
  if (tempFolderList.find((x) => x.id === folderList[folder].parent_folder)) {
    // tempFolderList.find((x) => x.id === f[folder].parent_folder).children.push(tempChildFolder)
    tempFolderList.push(tempChildFolder)
    return tempFolderList;
  }
  else {
    for (var f in tempFolderList) {
      var attt = this.addToTree(tempFolderList[f].children, folder, tempChildFolder, folderList)
      if (attt) {
        tempFolderList[f] = attt
        return tempFolderList
      }
      else {
        return false
      }
    }
  }
    },

标签: javascriptvue.js

解决方案


首先,使用其 id 创建一个文件夹映射,以便以后更快地访问:

let folders = response.data.folders

let folderMap = folders.reduce((map, folder) => {
  map[folder.id] = folder
  return map
}, {})

然后只过滤根文件夹:

let folderTree = folders.filter(folder => folder.parent_folder === null)

然后递归解析文件夹子项:

let resolveFolder = function (folder) {
  let newFolder = { ...folderMap[folder.id] } // shallow copy the folder object here because of the next line we will mutate it
  if (newFolder.folders) {
    newFolder.folders = newFolder.folders.map(resolveFolder)
  }
  return newFolder
}

folderTree.map(resolveFolder)

let folders = [
  {
    "id": 7,
    "name": "Folder 1",
    "parent_folder": null,
    "folders": [
      {
        "id": 8,
        "name": "Folder 1-1",
        "parent_folder": 7
      },
      {
        "id": 10,
        "name": "Folder 1-2",
        "parent_folder": 7
      }
    ]
  },
  {
    "id": 8,
    "name": "Folder 1-1",
    "parent_folder": 7,
    "folders": [
      {
        "id": 9,
        "name": "Folder 1-1-1",
        "parent_folder": 8
      }
    ]
  },
  {
    "id": 9,
    "name": "Folder 1-1-1",
    "parent_folder": 8
  },
  {
    "id": 10,
    "name": "Folder 1-2",
    "parent_folder": 7
  }
]

let folderMap = folders.reduce((map, folder) => {
  map[folder.id] = folder
  return map
}, {})

let resolveFolder = function (folder) {
  return {
    ...folderMap[folder.id],
    folders: folderMap[folder.id].folders?.map(resolveFolder)
  }
}

let folderTree = folders
  .filter(folder => folder.parent_folder === null)
  .map(resolveFolder)

console.log(folderTree)


推荐阅读