JavaScript前端面试扁平数据转tree与tree数据扁平化


Posted in Javascript onJune 14, 2022

一、写在前面

有时我们拿到的数据的数据结构可能不是理想的,那么此时就要求前端程序员,具有改造数据的能力。例如拿到扁平的数据, 但我们要应用在 tree 树形组件或 Cascader 级联选择器组件中,这样的组件要求数据结构是非扁平的的具有层级递进关系的 tree 结构。

总之就是说,提供数据的接口给到的数据,未必符合要求,而当我们又无法令他人为为我们改变时,需求和要求就来到了前端程序员这里, 所以得具备这样的数据处理能力。

下面是将举两个数据改造的例子:

  • 一是扁平化,具有层级递进关系的 tree 数据,转换为扁平结构的的 flat 数据
  • 二是反扁平化,扁平结构的 flat 数据,转换为具有层级递进关系的 tree 数据

二、正文部分

2.1 扁平数据转为 tree 数据

扁平化函数

/**
   * 扁平化:将具有层级递进关系结构的 tree 数据扁平化
   * 
   * @param treeList 有层级递进关系结构的 tree 数据
   * @param flatList 用于接收扁平化结果的变量
   * @returns {*} 返回扁平化结果
   */
  function treeToFlat (treeList, flatList) {
    // flatList.length > 9999 是考虑底线保护原则,出于极限保护的目的设置的,可不设或按需设置。
    if (flatList.length > 9999) {
      return
    }
    treeList.map(e => {
      flatList.push(e)
      // 递归:有条件的自己调用自己,条件是 e.children.length 为真
      if (e.children && e.children.length) {
        treeToFlat(e.children, flatList)
      }
    })
    // console.log('扁平化后:', flatList)
    return flatList
  }

2.2 tree 数据转为扁平数据

反扁平化函数

/**
   * 反扁平化:将扁平结构的 flat 数据转换为具有层级递进关系结构的 tree 数据
   * 
   * @param flatList 扁平结构的数据
   * @param treeList 用于接收反扁平化结果的变量
   * @returns {*} 返回反扁平化结果
   */
  function flatToTree (flatList, treeList) {
    flatList.map(e => {
      // 以 e.pid===null,作为判断是不是根节点的依据,或者直接写死根节点(如果确定的话),
      // 具体以什么作为判断根节点的依据,得看数据的设计规则,通常是判断层级或是否代表根节点的标记
      if (e.pid === null) {
        // 避免出现重复数据
        const index = treeList.findIndex(sub => sub.id === e.id)
        if (index === -1) {
          treeList.push(e)
        }
      }
      flatList.map(e2 => {
        if (e2.pid === e.id) {
          // 避免出现重复数据
          const index = e.children.findIndex(sub => sub.id === e2.id)
          if (index === -1) {
            e.children.push(e2)
          }
        }
      })
    })

2.3 完整测试 demo

demo 测试结果截图如下:

JavaScript前端面试扁平数据转tree与tree数据扁平化

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>扁平数据转tree与tree数据扁平化 Demo</title>
</head>
<body>
<h1>扁平数据转tree与tree数据扁平化</h1>
<script>
  window.onload = function () {
    test()
  }
  function test () {
    let flatList = [],
      treeList = [
        {
          id: 1,
          pid: null,
          label: '第一层',
          value: '1',
          children: [
            {
              id: 2,
              pid: 1,
              label: '第二层1',
              value: '2.1',
              children: []
            },
            {
              id: 3,
              pid: 1,
              label: '第二层2',
              value: '2.2',
              children: []
            },
            {
              id: 4,
              pid: 1,
              label: '第二层3',
              value: '2.3',
              children: [
                {
                  id: 5,
                  pid: 4,
                  label: '第三层1',
                  value: '3.1',
                  children: []
                },
                {
                  id: 6,
                  pid: 4,
                  label: '第三层2',
                  value: '3.2',
                  children: []
                },
              ]
            },
          ]
        }
      ]
    console.log('原始 tree 数据:', JSON.parse(JSON.stringify(treeList)))
    // 扁平化
    console.log('tree =>flat,扁平化后:', treeToFlat(JSON.parse(JSON.stringify(treeList)), flatList))
    // 反扁平化,SON.parse(JSON.stringify()) 为了实现深拷贝
    console.log('flat =>tree,反扁平化后:', flatToTree(JSON.parse(JSON.stringify(flatList)), treeList))
  }
  /**
   * 扁平化:将具有层级递进关系结构的 tree 数据扁平化
   * 
   * @param treeList 有层级递进关系结构的 tree 数据
   * @param flatList 用于接收扁平化结果的变量
   * @returns {*} 返回扁平化结果
   */
  function treeToFlat (treeList, flatList) {
    // flatList.length > 9999 是考虑底线保护原则,出于极限保护的目的设置的,可不设或按需设置。
    if (flatList.length > 9999) {
      return
    }
    treeList.map(e => {
      flatList.push(e)
      // 递归:有条件的自己调用自己,条件是 e.children.length 为真
      if (e.children && e.children.length) {
        treeToFlat(e.children, flatList)
      }
    })
    // console.log('扁平化后:', flatList)
    return flatList
  }
  /**
   * 反扁平化:将扁平结构的 flat 数据转换为具有层级递进关系结构的 tree 数据
   * 
   * @param flatList 扁平结构的数据
   * @param treeList 用于接收反扁平化结果的变量
   * @returns {*} 返回反扁平化结果
   */
  function flatToTree (flatList, treeList) {
    flatList.map(e => {
      // 以 e.pid===null,作为判断是不是根节点的依据,或者直接写死根节点(如果确定的话),
      // 具体以什么作为判断根节点的依据,得看数据的设计规则,通常是判断层级或是否代表根节点的标记
      if (e.pid === null) {
        // 避免出现重复数据
        const index = treeList.findIndex(sub => sub.id === e.id)
        if (index === -1) {
          treeList.push(e)
        }
      }
      flatList.map(e2 => {
        if (e2.pid === e.id) {
          // 避免出现重复数据
          const index = e.children.findIndex(sub => sub.id === e2.id)
          if (index === -1) {
            e.children.push(e2)
          }
        }
      })
    })
    // console.log('反扁平化后:', treeList)
    return treeList
  }
</script>
</body>
</html>

三、写在后面

这两个扁平化与反扁平化写法,感觉还有值得优化的方法,但暂时想不到。

此外,递归的应用也是值得注意的地方。

我理解的递归:有条件的自己调用自己

以上就是JavaScript前端面试扁平数据转tree与tree数据扁平化的详细内容,更多关于扁平数据转tree数据扁平化的资料请关注三水点靠木其它相关文章!


Tags in this post...

Javascript 相关文章推荐
漂亮的widgets,支持换肤和后期开发新皮肤(2007-4-27已更新1.7alpha)
Apr 27 Javascript
Ext第一周 史上最强学习笔记---GridPanel(基础篇)
Dec 29 Javascript
JavaScript使用原型和原型链实现对象继承的方法详解
Apr 05 Javascript
AngularJS全局警告框实现方法示例
May 18 Javascript
seajs模块压缩问题与解决方法实例分析
Oct 10 Javascript
详解如何在项目中使用jest测试react native组件
Feb 09 Javascript
Vue唯一可以更改vuex实例中state数据状态的属性对象Mutation的讲解
Jan 18 Javascript
jquery实现Ajax请求的几种常见方式总结
May 28 jQuery
javascript实现图片轮播代码
Jul 09 Javascript
通过js示例讲解时间复杂度与空间复杂度
Aug 06 Javascript
JS实现拼图游戏
Jan 29 Javascript
vue-cli3 取消eslint校验代码的解决办法
Jan 16 Javascript
vue如何在data中引入图片的正确路径
Jun 05 #Vue.js
Vue Mint UI mt-swipe的使用方式
Jun 05 #Vue.js
vue @ ~ 相对路径 路径别名设置方式
Jun 05 #Vue.js
vue css 相对路径导入问题级踩坑记录
Jun 05 #Vue.js
vue中data里面的数据相互使用方式
Jun 05 #Vue.js
Vue 打包后相对路径的引用问题
Jun 05 #Vue.js
vue实现在data里引入相对路径
Jun 05 #Vue.js
You might like
php中目录,文件操作详谈
2007/03/19 PHP
PHP 删除文件与文件夹操作 unlink()与rmdir()这两个函数的使用
2011/07/17 PHP
php伪静态之APACHE篇
2014/06/02 PHP
php中的字符编码转换函数用法示例
2014/10/20 PHP
PHP随机数 C扩展随机数
2016/05/04 PHP
php.ini中date.timezone设置详解
2016/11/20 PHP
为Yahoo! UI Extensions Grid增加内置的可编辑器
2007/03/10 Javascript
8个超棒的学习 jQuery 的网站 推荐收藏
2011/04/02 Javascript
JS 两个字符串时间的天数差计算
2013/08/25 Javascript
js 获取、清空input type=&quot;file&quot;的值示例代码
2014/02/19 Javascript
Node.js和PHP根据ip获取地理位置的方法
2014/03/14 Javascript
Ext修改GridPanel数据和字体颜色、css属性等
2014/06/13 Javascript
JQuery球队选择实例
2015/05/18 Javascript
用jquery快速解决IE输入框不能输入的问题
2016/10/04 Javascript
探究JavaScript中的五种事件处理程序方式
2016/12/07 Javascript
angularjs $http实现form表单提交示例
2017/06/09 Javascript
js传递数组参数到后台controller的方法
2018/03/29 Javascript
JavaScript设计模式之构造函数模式实例教程
2018/07/02 Javascript
JS加密插件CryptoJS实现的Base64加密示例
2020/08/16 Javascript
vue 对象添加或删除成员时无法实时更新的解决方法
2019/05/01 Javascript
jQuery冲突问题解决方法
2021/01/19 jQuery
[01:01:36]Optic vs paiN 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
Python中的生成器和yield详细介绍
2015/01/09 Python
Python使用django搭建web开发环境
2017/06/09 Python
python 实现数字字符串左侧补零的方法
2018/12/04 Python
正确理解Python中if __name__ == '__main__'
2019/01/24 Python
Python逐行读取文件中内容的简单方法
2019/02/26 Python
Python基于pygame实现单机版五子棋对战
2019/12/26 Python
基于Python和C++实现删除链表的节点
2020/07/06 Python
Python安装Bs4的多种方法
2020/11/28 Python
如何用python写个模板引擎
2021/01/14 Python
猎人靴英国官网:Hunter Boots
2017/02/02 全球购物
污水厂厂长岗位职责
2014/01/04 职场文书
任命书怎么写
2014/06/04 职场文书
反对形式主义、官僚主义、享乐主义和奢靡之风整改措施
2014/09/17 职场文书
Springboot配置suffix指定mvc视图的后缀方法
2021/07/03 Java/Android