详解JavaScript中扁平与树形数据的转换

我来为你详细讲解“详解JavaScript中扁平与树形数据的转换”的完整攻略。

前言

在前端开发中,我们经常需要把扁平数据转换为树形结构数据,或者将树形结构数据转换为扁平数据,这种数据格式转换操作在开发中很常见。本篇文章将对JavaScript中扁平数据和树形结构数据的转换进行详细介绍。

扁平数据与树形结构数据

扁平数据

扁平数据是指没有嵌套结构,所有数据都在同一层级下的数据结构。例如:

const flatData = [
  {id: 1, name: 'A', parentId: null},
  {id: 2, name: 'B', parentId: null},
  {id: 3, name: 'C', parentId: 1},
  {id: 4, name: 'D', parentId: 1},
  {id: 5, name: 'E', parentId: 2},
  {id: 6, name: 'F', parentId: 4},
  {id: 7, name: 'G', parentId: 5},
];

上面的扁平数据中,id表示节点编号,name表示节点名称,parentId表示父节点编号。

树形结构数据

树形结构数据是指具有嵌套关系的数据结构,例如:

const treeData = [
  {
    id: 1,
    name: 'A',
    children: [
      {
        id: 3,
        name: 'C',
      },
      {
        id: 4,
        name: 'D',
        children: [
          {
            id: 6,
            name: 'F',
          }
        ]
      }
    ]
  },
  {
    id: 2,
    name: 'B',
    children: [
      {
        id: 5,
        name: 'E',
        children: [
          {
            id: 7,
            name: 'G',
          }
        ]
      }
    ]
  }
];

上述树形数据中,每个节点都有一个唯一的编号id和名称name,还有子节点children。

扁平数据转树形结构数据

在具体实现扁平数据转树形结构数据的过程中,我们可以通过遍历扁平数据,将每个节点依次添加到相应的父节点的children数组中。

下面是一个示例代码,具体的注释可以帮助理清转换的流程:

function flatToTree(flatData) {
  // 通过map构造一个节点编号到节点对象的映射
  const nodeMap = flatData.reduce((map, node) => {
    map[node.id] = node;
    return map;
  }, {});

  // 通过遍历构造树形结构
  const treeData = [];
  for (const node of flatData) {
    const parent = nodeMap[node.parentId];
    if (parent) {
      // 如果有父节点,就将自己加入父节点的children数组中
      (parent.children || (parent.children = [])).push(node);
    } else {
      // 如果没有父节点,就认为自己是根节点
      treeData.push(node);
    }
  }
  return treeData;
}

上面的代码首先是通过map构造一个节点编号到节点对象的映射,这样方便我们在后续的遍历操作中快速找到父节点对象。接着,遍历整个扁平数据,通过nodeMap找到每个节点的父节点,然后将自己加入父节点的children数组中,最后返回整个树形结构数据。

下面我们执行一下上面代码的示例:

const flatData = [
  {id: 1, name: 'A', parentId: null},
  {id: 2, name: 'B', parentId: null},
  {id: 3, name: 'C', parentId: 1},
  {id: 4, name: 'D', parentId: 1},
  {id: 5, name: 'E', parentId: 2},
  {id: 6, name: 'F', parentId: 4},
  {id: 7, name: 'G', parentId: 5},
];

const treeData = flatToTree(flatData);
console.log(treeData);

输出结果:

[
  {
    "id": 1,
    "name": "A",
    "children": [
      {
        "id": 3,
        "name": "C"
      },
      {
        "id": 4,
        "name": "D",
        "children": [
          {
            "id": 6,
            "name": "F"
          }
        ]
      }
    ]
  },
  {
    "id": 2,
    "name": "B",
    "children": [
      {
        "id": 5,
        "name": "E",
        "children": [
          {
            "id": 7,
            "name": "G"
          }
        ]
      }
    ]
  }
]

树形结构数据转扁平数据

接下来让我们来介绍树形结构数据转扁平数据。

在具体实现树形结构数据转扁平数据的过程中,我们可以通过递归遍历整个树形结构,将每个节点依次添加到扁平数据中。

下面是一个示例代码,具体的注释可以帮助理清转换的流程:

function treeToFlat(treeData) {
  const flatData = [];

  function traverse(node, parentId) {
    // 构造节点对象
    const flatNode = {
      id: node.id,
      name: node.name,
      parentId
    };
    flatData.push(flatNode);

    // 遍历子节点
    if (node.children) {
      for (const child of node.children) {
        traverse(child, node.id);
      }
    }
  }

  // 从根节点开始遍历
  for (const node of treeData) {
    traverse(node, null);
  }

  return flatData;
}

上面的代码首先是通过traverse函数递归遍历整个树形结构,将每个节点构造成扁平数据格式,然后添加到flatData数组中。关键在于递归调用traverse函数时要传入父节点的id作为parentId,这样可以准确地还原出节点的父子关系。

下面我们执行一下上面代码的示例:

const treeData = [
  {
    id: 1,
    name: 'A',
    children: [
      {
        id: 3,
        name: 'C',
      },
      {
        id: 4,
        name: 'D',
        children: [
          {
            id: 6,
            name: 'F',
          }
        ]
      }
    ]
  },
  {
    id: 2,
    name: 'B',
    children: [
      {
        id: 5,
        name: 'E',
        children: [
          {
            id: 7,
            name: 'G',
          }
        ]
      }
    ]
  }
];

const flatData = treeToFlat(treeData);
console.log(flatData);

输出结果:

[
  {
    "id": 1,
    "name": "A",
    "parentId": null
  },
  {
    "id": 3,
    "name": "C",
    "parentId": 1
  },
  {
    "id": 4,
    "name": "D",
    "parentId": 1
  },
  {
    "id": 6,
    "name": "F",
    "parentId": 4
  },
  {
    "id": 2,
    "name": "B",
    "parentId": null
  },
  {
    "id": 5,
    "name": "E",
    "parentId": 2
  },
  {
    "id": 7,
    "name": "G",
    "parentId": 5
  }
]

总结

以上就是将扁平数据转换为树形数据和将树形数据转换为扁平数据的JavaScript实现方法。在实际项目中,我们需要依据具体业务场景,选用合适的方法来处理数据,本文的方法旨在提供一种思路,读者可以根据自己的需要灵活应用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解JavaScript中扁平与树形数据的转换 - Python技术站

(0)
上一篇 2023年6月8日
下一篇 2023年6月8日

相关文章

  • NodeJS测试框架mocha入门教程

    当你打算使用NodeJS编写代码进行开发时,测试框架是很重要的一环。Mocha作为最流行的NodeJS测试框架之一,可以让你编写更优雅的单元测试。 本篇文章将介绍如何开始使用Mocha测试框架编写测试用例。下面我们将从以下几个方面逐一讲解: 安装Mocha 编写简单的测试用例 使用断言库chai.js 运行多个测试用例 配置文件 1. 安装Mocha 首先,…

    node js 2023年6月8日
    00
  • node实现封装一个图片拼接插件

    下面给出详细的步骤说明。 1. 安装依赖 由于本项目需要使用到图片处理和文件操作相关的模块,因此需要先安装相应的依赖包,包括jimp和fs,其中jimp用来实现图片的处理功能,fs用来实现文件操作的功能 npm install jimp –save 2. 创建项目工程 创建一个空目录用于存储该项目文件,并在该目录下初始化一个node工程: mkdir im…

    node js 2023年6月8日
    00
  • 如何利用nodejs实现命令行游戏

    下面是基于Node.js实现命令行游戏的完整攻略: 1.了解Node.js 首先,你需要了解Node.js是一个什么样的东西。Node.js是一个基于Chrome V8 JavaScript引擎的开源、跨平台的后端JavaScript运行环境,可以用于快速构建高性能、可扩展的网络应用程序。Node.js它提供了一些内置模块,包括文件系统、HTTP等,使得可以…

    node js 2023年6月8日
    00
  • Node.JS获取GET,POST数据之queryString模块使用方法详解

    下面是详细讲解“Node.JS获取GET,POST数据之queryString模块使用方法详解”的完整攻略。 什么是queryString模块? Node.js中的queryString模块可以用于解析和格式化URL查询字符串(query string)。它是一个内置模块,因此无需单独安装。queryString模块主要包含两个方法: queryString…

    node js 2023年6月8日
    00
  • JS常用跨域方法实现原理解析

    以下是针对“JS常用跨域方法实现原理解析”的完整攻略: 理解同源策略 同源策略是浏览器最核心的一个安全特性,它决定了我们在浏览器中使用 JavaScript 发起网络请求时,具体哪些服务可被访问。同源策略是指执行在一个源(协议 + 域名 + 端口)内的脚本只能获取和操作相同源下的文档或脚本的一部分内容,而访问其他源下的数据则会被浏览器所限制。 例如,我们的网…

    node js 2023年6月8日
    00
  • 完美解决node.js中使用https请求报CERT_UNTRUSTED的问题

    当我们使用Node.js中的https模块发送请求时,有时会遇到一个CERT_UNTRUSTED的报错问题,这是因为我们请求的是一个自签名的网站证书,而Node.js默认不信任这类证书。本攻略将介绍如何完美解决这个问题。 问题原因 在https请求过程中,客户端会验证服务器的证书是否信任。如果服务器证书是由权威机构颁发的,那么客户端会信任该证书;如果是自签名…

    node js 2023年6月8日
    00
  • node学习笔记之读写文件与开启第一个web服务器操作示例

    下面详细讲解“node学习笔记之读写文件与开启第一个web服务器操作示例”的完整攻略。 读写文件 在 Node.js 中,可以使用 fs 模块来进行文件的操作。具体步骤如下: 引入 fs 模块:const fs = require(‘fs’) 使用 fs.readFile() 方法来读取文件内容,该方法需要传入两个参数:文件路径和回调函数。 文件路径可以是相…

    node js 2023年6月8日
    00
  • node.js多个异步过程中判断执行是否完成的解决方案

    在node.js中,异步操作非常常见,实现异步操作的方法有很多,比如回调函数、Promise、async/await等。但是在多个异步过程中判断执行是否完成时,会遇到一些问题。本文将详细讲述node.js中多个异步过程中判断执行是否完成的解决方案。 问题 在多个异步过程中判断执行是否完成的问题,可以用以下示例来说明。假设我们有3个异步函数需要执行,分别是: …

    node js 2023年6月8日
    00
合作推广
合作推广
分享本页
返回顶部