【问题标题】:Processing some JSON to output a a JSON object that represents a folder structure处理一些 JSON 以输出表示文件夹结构的 JSON 对象
【发布时间】:2021-01-19 20:41:15
【问题描述】:

给定以下两个json对象,其中files代表一个目录数组,colourCodes代表一个颜色到status的映射,我想处理文件数组(其实就是一个目录列表) 来确定目录结构。在每个file 中,folderColorRgb 映射到一个状态(可以从colourCodes 常量中查找状态 - 如果colourCodes 中不存在颜色,则状态为Not covered)。

const colourCodes = {
    '#4986e7': 'Covered 100%',
    '#f83a22': 'Covered - weak',
}


const files = [
    {
        id: '1nn7_JlbwQCxyz7qecqEtbWvY4C9Q2S3M',
        name: 'cell biology',
        parents: [ '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR' ],
    },
    {
        id: '1bcNxav7kq--E1Qabu3tcXk9DxvRdCcgR',
        name: 'ecology',
        parents: [ '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR' ],
        folderColorRgb: '#4986e7'
    },
    {
        id: '1MmkaP5xveClf6BfrhjHyYv4Q_Vaq1vf_',
        name: 'infection and response',
        parents: [ '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR' ],
        folderColorRgb: '#8f8f8f'
    },
    {
        id: '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR',
        name: 'biology',
        parents: [ '1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2' ],
        folderColorRgb: '#16a765'
    },
    {
        id: '1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2',
        name: 'science',
        parents: [ '0AF24wY_V36dlUk9PVA' ],
        folderColorRgb: '#a47ae2'
    },
    {
        id: 'physics-id',
        name: 'physics',
        parents: [ '1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2' ],
        folderColorRgb: '#16a765'
    },

    {
        id: 'electricity-id',
        name: 'electricity',
        parents: [ 'physics-id' ],
        folderColorRgb: '#f83a22'
    },
]

我想要达到的结果如下:

{
  science: {
    biology: {
      'cell biology': { status: 'Not covered' },
      ecology: { status: 'Covered 100%' },
      'infection and response': { status: 'Not covered' },
    },
    physics: { electricity: { status: 'Covered - weak' } },
  },
}

所以它是 JSON 中表示的 files 数组的文件夹结构。你可以做以下假设

  • 每个文件的parents 数组将始终包含一个parentId,即指向父文件夹的链接。
  • 所有parentId's 在文件数组中都以id 的形式存在 - 除了顶级目录(例如,在这种情况下为科学,files 中不存在科学的 parentId。

有人知道实现这一目标的好方法吗?

【问题讨论】:

    标签: javascript node.js json functional-programming


    【解决方案1】:

    我提出了以下解决方案,但不会接受我自己的答案,并将问题悬而未决,看看是否有人有更优雅的方法

    const colourCodes = {
        '#4986e7': 'Covered 100%',
        '#f83a22': 'Covered - weak',
    }
    
    
    const files = [
        {
            id: '1nn7_JlbwQCxyz7qecqEtbWvY4C9Q2S3M',
            name: 'cell biology',
            parents: [ '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR' ],
        },
        {
            id: '1bcNxav7kq--E1Qabu3tcXk9DxvRdCcgR',
            name: 'ecology',
            parents: [ '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR' ],
            folderColorRgb: '#4986e7'
        },
        {
            id: '1MmkaP5xveClf6BfrhjHyYv4Q_Vaq1vf_',
            name: 'infection and response',
            parents: [ '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR' ],
            folderColorRgb: '#8f8f8f'
        },
        {
            id: '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR',
            name: 'biology',
            parents: [ '1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2' ],
            folderColorRgb: '#16a765'
        },
        {
            id: '1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2',
            name: 'science',
            parents: [ '0AF24wY_V36dlUk9PVA' ],
            folderColorRgb: '#a47ae2'
        },
        {
            id: 'physics-id',
            name: 'physics',
            parents: [ '1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2' ],
            folderColorRgb: '#16a765'
        },
    
        {
            id: 'electricity-id',
            name: 'electricity',
            parents: [ 'physics-id' ],
            folderColorRgb: '#f83a22'
        },
    ]
    
    function getStatus(folder) {
        return colourCodes[folder.folderColorRgb] || 'Not covered'
    }
    
    function extractFolderStructure(parentFolder) {
    
        const children = files.filter(f => f.parents.includes(parentFolder.id))
        if (children.length==0) {
            const status = getStatus(parentFolder)
            return {[parentFolder.name]: {status}}
        }
        const childObjects = children.map(c => {
            const returnObj = extractFolderStructure(c)
            return returnObj
        })
    
        const fullObj = {[parentFolder.name] : {}}
        childObjects.forEach(co => {
            fullObj[parentFolder.name][Object.keys(co)[0]] = co[Object.keys(co)[0]]
        })
    
        return fullObj
    }
    
    console.log(extractFolderStructure(files.find(f => f.name === 'science')))
    

    【讨论】:

      【解决方案2】:

      我认为首先将您的输入转换为包含您需要的内容的格式会有所帮助:

      const Node = ({ id, name, parents: [parentId], folderColorRgb }) => ({
        id,
        name,
        parentId,
        status: colourCodes[folderColorRgb] || null,
        children: []
      });
      

      现在更容易编写输出所需格式的函数:

      Node.toObj = node => ({
        [node.name]: node.children.length
          ? Object.assign(...node.children.map(Node.toObj))
          : { status: node.status || "Not covered" }
      });
      

      现在的挑战是:

      • 将孩子与父母联系起来
      • 找到根节点

      我选择创建一个{ nodeId: node } 的索引和一个用于创建链接并存储根节点的forEach

      const foldersById = Object.fromEntries(
        files
          .map(Node)
          .map(f => [f.id, f])
      );
      
      // Note: this mutates the nodes
      let root = null;
      Object
        .values(foldersById)
        .forEach(f => {
          const parent = foldersById[f.parentId];
          if (parent) parent.children.push(f);
          else root = f;
        });
      

      然后,您通过调用Node.toObj(root) 输出结果。

      可运行的 sn-p 中的完整代码:

      const colourCodes = {
        '#4986e7': 'Covered 100%',
        '#f83a22': 'Covered - weak',
      }
      
      
      const files = [{
          id: '1nn7_JlbwQCxyz7qecqEtbWvY4C9Q2S3M',
          name: 'cell biology',
          parents: ['1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR'],
        },
        {
          id: '1bcNxav7kq--E1Qabu3tcXk9DxvRdCcgR',
          name: 'ecology',
          parents: ['1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR'],
          folderColorRgb: '#4986e7'
        },
        {
          id: '1MmkaP5xveClf6BfrhjHyYv4Q_Vaq1vf_',
          name: 'infection and response',
          parents: ['1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR'],
          folderColorRgb: '#8f8f8f'
        },
        {
          id: '1YewXh1WkIVIxOuHTV9acYG7WDE55EnPR',
          name: 'biology',
          parents: ['1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2'],
          folderColorRgb: '#16a765'
        },
        {
          id: '1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2',
          name: 'science',
          parents: ['0AF24wY_V36dlUk9PVA'],
          folderColorRgb: '#a47ae2'
        },
        {
          id: 'physics-id',
          name: 'physics',
          parents: ['1WVm7S1fw8Neg7FM80QNxcMWvVc_w_Jt2'],
          folderColorRgb: '#16a765'
        },
      
        {
          id: 'electricity-id',
          name: 'electricity',
          parents: ['physics-id'],
          folderColorRgb: '#f83a22'
        },
      ]
      
      
      
      const Node = ({
        id,
        name,
        parents: [parentId],
        folderColorRgb
      }) => ({
        id,
        name,
        parentId,
        status: colourCodes[folderColorRgb] || null,
        children: []
      });
      
      Node.toObj = node => ({
        [node.name]: node.children.length ?
          Object.assign(...node.children.map(Node.toObj)) :
          { status: node.status || "Not covered" }
      });
      
      
      
      const foldersById = Object.fromEntries(
        files
        .map(Node)
        .map(f => [f.id, f])
      );
      
      // Note: this mutates the nodes
      let root = null;
      Object
        .values(foldersById)
        .forEach(f => {
          const parent = foldersById[f.parentId];
          if (parent) parent.children.push(f);
          else root = f;
        });
      
      console.log(Node.toObj(root));
      .as-console-wrapper {
        min-height: 100%;
      }

      【讨论】:

      • 感谢@user3297291,这是一个非常巧妙的解决方案。我将在星期三接受一个答案.. 目前你肯定有最好的解决方案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-13
      • 2023-01-12
      • 2019-03-01
      相关资源
      最近更新 更多