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

yizhihongxing

我来为你详细讲解“详解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日

相关文章

  • Node.js Koa2使用JWT进行鉴权的方法示例

    以下是详细讲解“Node.js Koa2使用JWT进行鉴权的方法示例”的完整攻略。 什么是JWT JSON Web Token (JWT) 是一个标准,用于在不同的系统之间传输信息作为 JSON 对象。JWT 可以使用秘密(使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对来进行签名。JWT 可以包含用户的身份信息,以及应用程序需要的任何其…

    node js 2023年6月8日
    00
  • 详解Node.js 中使用 ECDSA 签名遇到的坑

    详解Node.js 中使用 ECDSA 签名遇到的坑 什么是ECDSA ECDSA,全称椭圆曲线数字签名算法(Elliptic Curve Digital Signature Algorithm),是一种基于椭圆曲线密码学的签名算法。与传统的RSA、DSA等算法相比,ECDSA在强度和速度方面都有很大的优势。 Node.js中使用ECDSA签名 在Node.…

    node js 2023年6月8日
    00
  • 使用 Node.js 开发资讯爬虫流程

    使用 Node.js 开发资讯爬虫流程 本文将详细讲解如何使用 Node.js 开发资讯爬虫,包括编写爬虫程序和爬虫流程设计。 爬虫程序编写 爬虫程序是指通过网络爬取网站内容的程序。在 Node.js 中,使用第三方模块 request 和 cheerio 可以方便地编写爬虫程序。 示例一:爬取知乎首页热榜内容 const request = require…

    node js 2023年6月8日
    00
  • Node.js查找当前目录下文件夹实例代码

    Node.js是一种基于Chrome V8引擎的JavaScript运行环境,可以执行JavaScript代码,因此可以用来查找当前目录下的文件夹。下面是完整攻略及两条示例说明。 使用Node.js查找当前目录下文件夹实例代码 1. 使用fs模块 Node.js提供了fs模块,可以用来访问文件系统。通过fs模块的readdirSync()方法可以获取当前路径…

    node js 2023年6月8日
    00
  • js实现axios限制请求队列

    要实现 axios 的请求队列限制,一般需要使用队列或者 Promise.all 的方式来统一管理请求。以下是实现过程的详细攻略。 1. 队列方式实现axios请求队列限制 使用队列来实现 axios 请求队列限制有以下几个步骤: 定义一个队列,用来存储请求。 const requestQueue = []; 定义一个函数,用来从队列中取出一个请求,并发送该…

    node js 2023年6月8日
    00
  • Linux环境部署node服务并启动详细步骤

    下面是详细讲解Linux环境部署Node服务并启动的步骤: 环境准备 在开始部署Node服务之前,需要确保环境中已经安装了以下软件和工具: Linux操作系统,例如Ubuntu、CentOS Node.js运行环境 NPM包管理工具 Git版本控制工具 如果当前系统还没有安装这些软件或工具,可以通过以下方式进行安装: 安装Node.js和NPM 在Ubunt…

    node js 2023年6月8日
    00
  • 基于Nodejs的Tcp封包和解包的理解

    下面我将为您详细讲解“基于Nodejs的Tcp封包和解包的理解”的完整攻略。 1. 什么是TCP封包和解包 在网络传输中,常使用TCP协议进行数据传输。但是,传输的数据都是以二进制编码的形式进行传输的,所以我们需要进行TCP封包和解包以便正确的处理传输数据。 TCP封包:TCP封包是指将数据按照TCP协议的规定打包成一个个二进制数据包。每个TCP数据包包括T…

    node js 2023年6月8日
    00
  • 如何正确使用Nodejs 的 c++ module 链接到 OpenSSL

    使用Node.js的C++ native扩展可以使用Node.js的高效性,而使用OpenSSL提供了安全加密通信的功能。在下面的攻略中,我将向您展示如何正确使用Node.js的C++模块将OpenSSL添加到您的项目中。 步骤 步骤1:设置OpenSSL 从OpenSSL官方网站下载和安装所需的软件包。请根据您的操作系统选择正确的软件包。 # Ubuntu…

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