JS使用reduce()方法处理树形结构数据

定义

reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。

reduce() 与forEach()、map()、filter()这些方法一样,也会对数组中的每一项进行遍历,但是reduce() 可以将遍历的前一个数组项产生的结果与当前遍历项进行运算。

语法

array.reduce(function(prev, cur, index, array){
    ...
}, init);

回调函数中的参数:

  • prev 必需。表示调用回调时的返回值,或者初始值 init。
  • cur 必需。表示当前元素。
  • index 可选。表示当前元素的索引。
  • array 表示原数组。
  • init 可选。初始值,作为第一次调用回调函数的第一个参数。

其中常用参数:prev 和 cur

注意:回调函数第一次执行时,prev和cur的取值有两种情况:如果调用reduce()时提供了初始值init,prev取init值,cur取数组中的第一个值,此时索引从0开始;如果没有提供初始值init,则prev取数组中的第一个值,cur取数组中的第二个值,此时索引从1开始。

实例

1. 没有传递初始值init

const arr = [1, 3, 5, 7]
arr.reduce(function(prev, cur, index, arr){
    console.log(prev, cur, index)
    return prev + cur
})

每次调用的参数和返回值如下表:

callback prev cur index array return value
第1次 1 3 1 [1, 3, 5, 7] 4
第2次 4 5 2 [1, 3, 5, 7] 9
第3次 9 7 3 [1, 3, 5, 7] 16

因为没有传入初始值,所以索引是从1开始,callback被调用三次,开始时prev的值为数组第一项1,cur的值为3,相加之后返回值4作为下一轮回调的prev值,然后继续下一轮的回调,直至完成后返回。

2. 传递初始值的情况下

const arr = [1, 3, 5, 7]
arr.reduce(function(prev, cur, index, arr){
    console.log(prev, cur, index)
    return prev + cur
}, 10)

每次调用的参数和返回值如下表:

callback prev cur index array return value
第1次 10 1 0 [1, 3, 5, 7] 11
第2次 11 3 1 [1, 3, 5, 7] 14
第3次 14 5 2 [1, 3, 5, 7] 19
第4次 19 7 3 [1, 3, 5, 7] 26

3. 数组去重

const arr = ['ab', 'v', 'd', 'ab', 'h', 'e', 'dc', 'e', 'e', 'f']
const newArr = arr.reduce(function(prev, cur){
    !prev.includes(cur) && prev.push(cur)
    return prev
}, [])
console.log(newArr) // ["ab", "v", "d", "h", "e", "dc", "f"]

执行的步骤如下:

  • 初始化一个空数组
  • 第一次调用时,prev 为初始值即空数组,cur 为数组中的第一项 arr[1],然后在 prev 中查找 cur 是否已经存在,如果不存在就将该项添加到 prev 中,并 prev 返回进入下一次回调
  • 第二次回调时,prev 为第一次的返回值,cur 为数组中的第二项 arr[2],然后在 prev 中查找 cur 是否已经存在,如果不存在就将该项添加到 prev 中,并 prev 返回进入下一次回调
  • 最后将 prev 这个数组返回

4. 利用 reduce 对数组中的 Object 对象进行分组及合并

//从后台获取的对象数组,根据对象的type进行分组合并成tree树形展示数据
const dataArr = [
    { type: '治理层', name: 'hive_82', reserve: '2', id: 1 },
    { type: '原始数据层', name: 'qwe', reserve: '1', id: 2 },
    { type: '贴源层', name: 'mysql_exchangis', reserve: '3', id: 3 },
    { type: '治理层', name: 'links_188', reserve: '1', id: 4 },
    { type: '贴源层', name: 'mysql_ces', reserve: '2', id: 5 }
]
const treeData = dataArr.reduce((cur, next) => {
    const obj = cur.find(curItem => curItem.label === next.type)
    if (obj) {
        if (obj.children.indexOf(next.id) === -1) { //去重处理
            obj.children.push({
                ...next,
                label: next.name
            })
        }
    } else {
        const newObj = {
            label: next.type,
            children: [{
                ...next,
                label: next.name
            }]
        }
        cur.push(newObj)
    }
    return cur
}, [])
​
// 合并后的结果:
treeData = [
    {
        label: '治理层',
        children: [
            { type: '治理层', name: 'hive_82', reserve: '2', id: 1, label: 'hive_82' },
            { type: '治理层', name: 'links_188', reserve: '1', id: 4, label: 'links_188' }
        ]
    },
    {
        label: '原始数据层',
        children: [
            { type: '原始数据层', name: 'qwe', reserve: '1', id: 2, label: 'qwe' }
        ]
    },
    {
        label: '贴源层',
        children: [
            { type: '贴源层', name: 'mysql_exchangis', reserve: '3', id: 3, label: 'mysql_exchangis' },
            { type: '治理层', name: 'mysql_ces', reserve: '2', id: 5, label: 'mysql_ces' }
        ]
    }
]

5. 利用 reduce 处理菜单后端返回的菜单结构

需要根据 parentId 将这些数据转换成层级结构。

方法一:

const dataArr = [
    {id: '18', name: '重置密码', parentId: '30',parentName: '用户管理'},
    {id: '13', name: '审计日志', parentId: '29', parentName: '系统管理'},
    {id: '29', name: '系统管理', parentId: '0', parentName: null},
    {id: '14', name: '修改', parentId: '33', parentName: '部门管理'},
    {id: '2', name: '用户列表', parentId: '30', parentName: '用户管理'},
    {id: '30', name: '用户管理', parentId: '29', parentName: '系统管理'},
    {id: '33', name: '部门管理', parentId: '0', parentName: null},
    {id: '37', name: '添加用户', parentId: '30', parentName: '用户管理'},
    {id: '6', name: '添加', parentId: '33', parentName: '部门管理'},
    {id: '7',name: '删除', parentId: '33', parentName: '部门管理'}
]
//创建菜单id的映射关系
const idMapping = dataArr.reduce((prev, next, i) => {
    prev[next.id] = i
    return prev
}, {})
​
const treeData = []
dataArr.map(el => {
    // 一级菜单
    if (el.parentId === '0') {
        treeData.push(el)
        return
    }

    // 通过映射找到父元素
    const parentEl = dataArr[idMapping[el.parentId]]
​
    // 把当前元素添加到父元素的`children`数组中
    parentEl.children = [...(parentEl.children || []), el]
})
console.log(treeData)

方法二:

//根据parentId创建映射关系
const result = dataArr.reduce((prev, next) => {
    prev[next.parentId] ? prev[next.parentId].push(next) : prev[next.parentId] = [next];
    return prev;
}, {});

Object.keys(result).map(key => {
    result[key].map((item, i) => {
        result[item.id] ? item.children = result[item.id] : ''
    });
})
this.treeData = result[0]
console.log(treeData)

还可以通过递归的方法来实现,具体就不赘述了

最后生成的数据结构如下图所示:

以上就是JS使用reduce()方法处理树形结构数据的详细内容,更多关于JS的资料请关注我们其它相关文章!

(0)

相关推荐

  • JS数组Reduce方法功能与用法实例详解

    本文实例讲述了JS数组Reduce方法功能与用法.分享给大家供大家参考,具体如下: 概述 一直以来都在函数式编程的大门之外徘徊,要入门的话首先得熟悉各种高阶函数,数组的reduce方法就是其中之一. reduce方法将会对数组元素从左到右依次执行reducer函数,然后返回一个累计的值.举个形象的例子:你要组装一台电脑,买了主板.CPU.显卡.内存.硬盘.电源...这些零件是组装电脑的必要条件. 装的过程可以简单概括为拆掉每个零件的包装,再装到一起.类比一下reduce函数就可以明白了,那些零件

  • JavaScript中reduce()的5个基本用法示例

    前言 reduce()方法可以搞定的东西,for循环,或者forEach方法有时候也可以搞定,那为啥要用reduce()?这个问题,之前我也想过,要说原因还真找不到,唯一能找到的是:通往成功的道路有很多,但是总有一条路是最捷径的,亦或许reduce()逼格更高... 语法 arr.reduce(callback,[initialValue]) reduce()方法对数组中的每一个元素执行一个reducer函数(由你提供),从而得到一个单一的输出值. reduce() 方法将一个数组中的所有元素还

  • js中的reduce()函数讲解

    定义: reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值.对空数组是不会执行回调函数的. 案例 1.数组求和 // 1.数组求和 var arr = [1,5,8,6,15,78,65,25,48,55] var sum = arr.reduce(function(total,currentValue){ return total+currentValue; }); console.log(sum);//306 var eachSum = 0;

  • Javascript数组方法reduce的妙用之处分享

    前言 Javascript数组方法中,相比map.filter.forEach等常用的迭代方法,reduce常常被我们所忽略,今天一起来探究一下reduce在我们实战开发当中,能有哪些妙用之处,下面从reduce语法开始介绍. 语法 array.reduce(function(accumulator, arrayElement, currentIndex, arr), initialValue) 若传入初始值,accumulator首次迭代就是初始值,否则就是数组的第一个元素:后续迭代中将是上一

  • JS数组reduce()方法原理及使用技巧解析

    1.语法 arr.reduce(callback,[initialValue]) reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组. callback (执行数组中每个值的函数,包含四个参数) 1.previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue)) 2.currentValue (数组中当前被处理的元素)

  • 浅谈JavaScript构造树形结构的一种高效算法

    引言 我们经常会碰到树形数据结构,比如组织层级.省市县或者动植物分类等等数据.下面是一个树形结构的例子: 在实际应用中,比较常见的做法是将这些信息存储为下面的结构,特别是当存在1对多的父/子节点关系时: const data = [ { id: 56, parentId: 62 }, { id: 81, parentId: 80 }, { id: 74, parentId: null }, { id: 76, parentId: 80 }, { id: 63, parentId: 62 }, {

  • js实现无限层级树形数据结构(创新算法)

    由于做项目的需要,把一个线性数组转成树形数组,在网上查了很多文章,觉得他们写的太复杂了,于是自己写了一个,在折腾了一下午终于把它写出来啦(激动.gif),用两个filter过滤器就搞定了,代码简洁明了,数据结构小白都能看懂. js代码:把扁平数据转成树形数据 function setTreeData(source){ let cloneData = JSON.parse(JSON.stringify(source)) // 对源数据深度克隆 return cloneData.filter(fat

  • javascript将扁平的数据转为树形结构的高效率算法

    当我们需要将一个一维数组转换成一个多层结构的时候,最简单但是最慢的就是多个for循环嵌套,但是这样做有一些缺点,那就是效率太低.而且有多少层就需要嵌套几个for循环,不好用. 我实现了用O(n)级算法将 一个扁平的数组即一维数组代表的菜单结构转换成一个多层级的菜单结构. 一位数组中每一个元素必须要包含以下属性: 拥有一个唯一的id 拥有一个parent_id, 这个id指向它父级的id 其他则为每一个元素中的一些信息,我这里是菜单,就有菜单的名称和url信息. 注: 在层级结构中,第一层的par

  • JS数组方法reduce的用法实例分析

    本文实例讲述了JS数组方法reduce的用法.分享给大家供大家参考,具体如下: 数组方法 reduce 用来迭代一个数组,并且把它累积到一个值中. 使用 reduce 方法时,你要传入一个回调函数,这个回调函数的参数是一个 累加器 (比如例子中的 previousVal) 和当前值 (currentVal). reduce 方法有一个可选的第二参数,它可以被用来设置累加器的初始值.如果没有在这定义初始值,那么初始值将变成数组中的第一项,而 currentVal 将从数组的第二项开始. 使用 re

  • JS使用reduce()方法处理树形结构数据

    定义 reduce() 方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值. reduce() 与forEach().map().filter()这些方法一样,也会对数组中的每一项进行遍历,但是reduce() 可以将遍历的前一个数组项产生的结果与当前遍历项进行运算. 语法 array.reduce(function(prev, cur, index, array){ ... }, init); 回调函数中的参数: prev 必需.表示调用回调时的返

  • 详解JS数组Reduce()方法详解及高级技巧

    基本概念 reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值. reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组. 语法: arr.reduce(callback,[initialValue]) callback (执行数组中每个值的函数,包含四个参数) previousValue (上

  • js利用reduce方法让你的代码更加优雅

    前言 在实际项目中,最常见可能是在计算.循环逻辑方面的处理,可以使用数组中reduce方法也可以解决很多的问题,使得你的代码风格更加优雅! reduce语法 arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue]) 参数说明 reducer函数需要接收4个参数分别是 callback Accumulator 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValu

  • JavaScript数组reduce()方法的语法与实例解析

    前言 reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值. reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组. Javascript数组方法中,相比map.filter.forEach等常用的迭代方法,reduce常常被我们所忽略,今天一起来探究一下reduce在我们实战开发当中,能有哪

  • 详解JS: reduce方法实现 webpack多文件入口

    1. reduce 方法介绍 1.1 简单场景 reduce 函数的设计意图就是方便进行叠加运算: var arr = [0, 1, 2, 3]; // reduce 实现累加 var total = arr.reduce(function (pre, cur){ return pre + cur; }, 0); console.log(total); // 6 上述代码中,reduce 方法有两个参数,第一个参数是一个 callback,用于进行计算的函数:第二个参数则是累加计算的初始值: 0

  • vue.js与element-ui实现菜单树形结构的解决方法

    由于业务需要,要求实现树形菜单,且菜单数据由后台返回,在网上找了几篇文章,看下来总算有了解决办法. 场景:根据业务要求,需要实现活动的树形菜单,菜单数据由后台返回,最后的效果图如下: 后台返回的数据格式是这个样子的: data=[{ pID:'1',//父ID name:'目录一', menuID:'m1',//本身ID isContent:false//判断是否是目录 }, { pID:'1', name:'目录二', menuID:'m2', isContent:false }, { pID

  • JS中的reduce()方法使用小结

    目录 一.语法 二.实例 三.其他相关方法 过去有很长一段时间,我一直很难理解 reduce() 这个方法的具体用法,平时也很少用到它.事实上,如果你能真正了解它的话,其实在很多地方我们都可以用得上,那么今天我们就来简单聊聊JS中 reduce() 的用法. 一.语法 arr.reduce(function(prev,cur,index,arr){ ... }, init); 其中, arr 表示原数组: prev 表示上一次调用回调时的返回值,或者初始值 init; cur 表示当前正在处理的

  • springboot构造树形结构数据并查询的方法

    因为项目需要,页面上需要树形结构的数据进行展示(类似下图这样),因此需要后端返回相应格式的数据. 不说废话,直接开干!!! 我这里用的是springboot+mybatis-plus+mysql,示例的接口是查询一级权限以及二级权限.三级权限整个权限树- 下面是导入的maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-

随机推荐