定义

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的资料请关注Devmax其它相关文章!

JS使用reduce()方法处理树形结构数据的更多相关文章

  1. html5 拖拽及用 js 实现拖拽功能的示例代码

    这篇文章主要介绍了html5 拖拽及用 js 实现拖拽,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. amaze ui 的使用详细教程

    这篇文章主要介绍了amaze ui 的使用详细教程,本文通过多种方法给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. swift皮筋弹动发射飞机ios源码

    这是一个款采用swift实现的皮筋弹动发射飞机游戏源码,游戏源码比较详细,大家可以研究学习一下吧。

  4. Swift与Js通过WebView交互

    开发环境:Swfit2.3XCode8.2基础概念jscontext,jscontext是代表JS的执行环境,通过-evaluateScript:方法就可以执行一JS代码JSValue,JSValue封装了JS与ObjC中的对应的类型,以及调用JS的API等JSExport,JSExport是一个协议,遵守此协议,就可以定义我们自己的协议,在协议中声明的API都会在JS中暴露出来,才能调用Swif

  5. JSCore swift

    如果双方相互引用,会造成循环引用,而导致内存泄露。以上是Jscore的基本使用,比较简单

  6. Swift WKWebView的js调用swift

    最近项目需求,需要用到JavaScriptCore和WebKit,但是网上的资源有限,而且比较杂,都是一个博客复制另外一个博客,都没有去实际敲代码验证,下面给大家分享一下我的学习过程。

  7. Swift WKWebView的swift调用js

    不多说,直接上代码:在html里面要添加的的代码,显示swift传过去的参数:这样就实现了swift给js传参数和调用!

  8. 在 Swift 專案中使用 Javascript:編寫一個將 Markdown 轉為 HTML 的編輯器

    你有強烈的好奇心,希望在你的iOS專案中使用JavaScript。jscontext中的所有值都是JSValue對象,JSValue類用於表示任意類型的JavaScript值。因此,我們既需要寫Swift代碼也要寫JavaScript代碼。此外,我們還會在JavaScript中按照這個類的定義來創建一個對象并對其屬性進行賦值。從Swift中呼叫JavaScript就如介紹中所言,JavaScriptCore中最主要的角色就是jscontext類。一個jscontext對象是位於JavaScript環境和本

  9. swift - WKWebView JS 交互

    本文介绍WKWebView怎么与js交互,至于怎么用WKWebView这里就不介绍了HTML代码APP调JS代码结果JS给APP传参数首先注册你需要监听的js方法名2.继承WKScriptMessageHandler并重写userContentController方法,在该方法里接收JS传来的参数3.结果

  10. swift 开发UIWebView跟JS的交互

    前言作为小白的我,才开始入门IOS,选择了swift来进行入门学习,学习做着公司一个简单的小小项目,该项目需要进行跟H5进行交互,然后我就开始研究了UIWebView的使用,其实基本原理跟Android的一样,因为我是Android开发的,所以就顺水推舟了。))//这里设置你需要加载的地址}overridefuncdidReceiveMemoryWarning(){super.didReceiveMemoryWarning()//disposeofanyresourcesthatcanberecreate

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部