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 相关文章推荐
jQuery TextBox自动完成条
Jul 22 Javascript
预加载css或javascript的js代码
Apr 23 Javascript
js 获取计算后的样式写法及注意事项
Feb 25 Javascript
javascript显示用户停留时间的简单实例
Aug 05 Javascript
js取消单选按钮选中并判断对象是否为空
Nov 14 Javascript
在页面加载完成后通过jquery给多个span赋值
May 21 Javascript
JavaScript函数柯里化详解
Apr 29 Javascript
深入浅析Vue全局组件与局部组件的区别
Jun 15 Javascript
Vue.set() this.$set()引发的视图更新思考及注意事项
Aug 30 Javascript
JQuery样式操作、click事件以及索引值-选项卡应用示例
May 14 jQuery
JavaScript中变量提升机制示例详解
Dec 27 Javascript
bootstrap-paginator服务器端分页使用方法详解
Feb 13 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 heredoc和phpwind的模板技术使用方法小结
2008/03/28 PHP
php download.php实现代码 跳转到下载文件(response.redirect)
2009/08/26 PHP
php 归并排序 数组交集
2011/05/10 PHP
优化WordPress中文章与评论的时间显示
2016/01/12 PHP
PHP创建多级目录的两种方法
2016/10/28 PHP
Flash对联广告的关闭按钮讨论
2007/01/30 Javascript
(转载)JavaScript中匿名函数,函数直接量和闭包
2007/05/08 Javascript
jquery UI 1.72 之datepicker
2009/12/29 Javascript
JS打开新窗口防止被浏览器阻止的方法
2015/01/03 Javascript
javascript解决IE6下hover问题的方法
2015/07/28 Javascript
全面解析Bootstrap表单使用方法(表单控件状态)
2015/11/24 Javascript
JS控制静态页面传递参数并获取参数应用
2016/08/10 Javascript
onmouseover事件和onmouseout事件全面理解
2016/08/15 Javascript
深入浅出 jQuery中的事件机制
2016/08/23 Javascript
详谈Ajax请求中的async:false/true的作用(ajax 在外部调用问题)
2017/02/10 Javascript
webpack4简单入门实例
2018/09/06 Javascript
vue+elementUI 复杂表单的验证、数据提交方案问题
2019/06/24 Javascript
Vue 利用指令实现禁止反复发送请求的两种方法
2019/09/15 Javascript
NProgress显示顶部进度条效果及使用详解
2019/09/21 Javascript
wxpython 学习笔记 第一天
2009/02/09 Python
在Python的循环体中使用else语句的方法
2015/03/30 Python
Python获取文件所在目录和文件名的方法
2017/01/12 Python
Python中查看变量的类型内存地址所占字节的大小
2019/06/26 Python
python 使用plt画图,去除图片四周的白边方法
2019/07/09 Python
Django组件content-type使用方法详解
2019/07/19 Python
python爬虫请求头的使用
2020/12/01 Python
CSS3 对过渡(transition)进行调速以及延时
2020/10/21 HTML / CSS
美国网上书店:Barnes & Noble
2018/08/15 全球购物
创建索引时需要注意的事项
2013/05/13 面试题
自荐信怎么写好
2013/11/11 职场文书
护士自我评价
2014/02/01 职场文书
会走路的树教学反思
2014/02/20 职场文书
腾讯广告词
2014/03/19 职场文书
党员教师四风自我剖析材料
2014/09/30 职场文书
红色经典观后感
2015/06/18 职场文书
公司致全体员工的感谢信
2019/06/24 职场文书