关于reduce:由浅入深讲解数组的reduce用法

数组中的reduce犹如一只魔法棒,通过它能够做一些黑科技一样的事件。本文从api解说到个别用法再到高级用法,由浅入深的讲一讲数组中的reduce。MDN链接 Array.prototype.reducereduce的api是这样的, reduce(callback(accumulator, currentValue[, index, array])[,initialValue])Callback accumulator 积攒的值currentValue 以后值index 以后下标array 以后数组initialValue 初始值reduce承受两个参数,回调函数和初识值,初始值是可选的。回调函数承受4个参数:积攒值、以后值、以后下标、以后数组。如果reduce的参数只有一个,那么积攒值一开始是数组中第一个值,如果reduce的参数有两个,那么积攒值一开始是出入的initialValue初始值。而后在每一次迭代时,返回的值作为下一次迭代的accumulator 积攒值。 重要阐明:如果未设置initialValue,那么reduce将应用您的第一个数组值作为第一次迭代的accumulator,从第二个数组元素上开始循环,从index=1开始(如果有的话) 以下是reduce的几种理论利用。 1. 将数组转化为对象将上面的数组转成以id为key的对象。 const userList = [ { id: 1, username: 'john', sex: 1, email: 'john@163.com' }, { id: 2, username: 'jerry', sex: 1, email: 'jerry@163.com' }, { id: 3, username: 'nancy', sex: 0, email: '' }];let objUserList = userList.reduce(keyByUserNameReducer, {})function keyByUserNameReducer(acculumator, currentValue, currentIndex, array) { return {...acculumator, [currentValue.id]: currentValue}}console.log(objUserList)// {// '1': { id: 1, username: 'john', sex: 1, email: 'john@163.com' },// '2': { id: 2, username: 'jerry', sex: 1, email: 'jerry@163.com' },// '3': { id: 3, username: 'nancy', sex: 0, email: '' }// }2. 将小数组开展成大数组将上面数组依照逗号宰割. ...

July 26, 2020 · 2 min · jiezi

javascript reduce详解及应用

reducecallback(一个在数组中每一项上调用的函数,接受四个参数:)previousValue(上一次调用回调函数时的返回值,或者初始值)currentValue(当前正在处理的数组元素)currentIndex(当前正在处理的数组元素下标)array(调用reduce()方法的数组)initialValue(可选的初始值。作为第一次调用回调函数时传给previousValue的值)概念一搜一大把,我们聊点我遇到的和理解的,见代码callback//reduce作为累加器 let arr = [1, 2, 3, 4, 5] let sum = arr.reduce((init, item, i, self) => { console.log(init---${init}, item---${item}, i---${i}, self---${self}) return init + item }) console.log(sum) //15分别看一下回调参数 见下图init默认为数组第一项,一次累加数组项,最后返回一项。item循环数组每一项i数组下标self当前调用reduce数组本身initialValue可选初始值,作为回调函数第一个参数的默认值,也是每次回调的返回值,见代码 let obj = { ‘/home’: { meta: { title: ‘首页’ }, component: ‘@/page/home’ }, ‘/question’: { meta: { title: ‘问题’ }, component: ‘@/page/question’ } } // 转化为数组 let map = [{ path: ‘/home’, meta: { title: ‘首页’ }, component: ‘@/page/home’ }, { path: ‘/question’, meta: { title: ‘问题’ }, component: ‘@/page/question’ }] let map1 = Object.keys(obj).reduce((arr, item) => { return (arr.push({ path: item, …obj[item] }), arr) }, []) console.log(map1)转化后效果这个栗子来自vue配置路由时遇到的,当时也是优化了好几个版本。接下来详细解释一下Object.keys(obj) //把obj转化为内容为key的数组reduce((arr,item)=>{})//上边已经解释过参数了,回调后边的参数[]:返回值默认值是一个空数组关于 return (arr.push({ path: item, …obj[item] }), arr)其实可以写成 arr.push({ path: item, …obj[item] }) return arr 具体请查看:javascript逗号操作符别急还有一个用法新鲜刚发现的。 //需求:判断数组每一项的end和下一项的start是否是递增的,返回ture or false let arr = [{ start: 1, end: 3 }, { start: 1, end: 3 }, { start: 4, end: 5 }] function isTure(arr) { let status = true arr.reduce((pro, next) => { if (pro.end >= next.start) { status = false return false } return next }) return status } console.log(isTure(arr))这里我们巧用了 reduce的返回值,每次返回当前项,这样两个参数始终为1,2 | 2,3|3,4依次类推明天map和filter ...

December 25, 2018 · 1 min · jiezi

详解数组中的reduce方法

前言 这几天面试被问到了数组的方法有哪些,回答得简直一塌糊涂,面试官说reduce的功能很强大,于是想对这个方法进行总结,在红宝书中对这个方法的描述并不算多,我也是参考了其他文章才进行总结的,下面就开始吧reduce的原理简介 在红宝书中,将这个方法定义为数组的归并方法,这个方法和迭代方法(map,forEach,filter…)一样,都会对数组进行遍历,reduce与他们不同的是函数的第一个参数得到的是迭代计算后的效果(看不懂没关系,继续往下看就会懂了)语法 这个方法接收两个参数:要执行的函数,要执行的函数中也可传入参数,分别为prev:上次调用函数的返回值cur:当前元素index:当前元素索引arr:被遍历的数组函数迭代的初始值举例没有设置函数的初始迭代值let arr = [1, 2, 3, 4];let sum = arr.reduce(function(prev, cur, index, arr) { console.log(prev, cur, index); return prev + cur;})console.log(arr, sum);运行结果:分析: 我们可以看到,在这里reduce的作用就是对这个数组进行求和,迭代了3次,函数迭代的初始值是1,也就是默认值(数组的第一项),prev的值是每次计算后的值,现在理解了吧!设置初始迭代值let arr = [1, 2, 3, 4];let sum = arr.reduce(function(prev, cur, index, arr) { console.log(prev, cur, index); return prev + cur;},5)console.log(arr, sum);运行结果:分析: 这里我们添加了一个初始的迭代值,也就是让prev从5开始计算,可以看到,这里迭代了4次,结果也加上了初始值。reduce的应用初级应用 最常见的应用一般就是求和以及求乘积了,比如说下面的例子:let arr = [1,2,3,4,5]console.log(arr.reduce((a,b) => a + b))//15console.log(arr.reduce((a,b) => a * b))//120高级应用计算数组中每个元素出现的次数let arr = [’name’,‘age’,’long’,‘short’,’long’,’name’,’name’] let arrResult = arr.reduce((pre,cur) =>{ console.log(pre,cur) if(cur in pre){ pre[cur]++ }else{ pre[cur] = 1 } return pre},{})console.log(arrResult)//结果:{name: 3, age: 1, long: 2, short: 1}运行结果:(第一个console.log)分析: 大概的解释一下,运行过程是这样的:由于设置了迭代初始值,pre的第一个值是一个空对象,此时cur为name,然后进行判断,发现在pre中没有name属性,所以就将name对应的属性值赋为1;后面没有重复的是一样的道理,如果碰到重复值,就会将该属性值加1,这样就能计算元素重复的次数了。(有没有觉得很神奇呀)去除数组中重复的元素let arrResult = arr.reduce((pre,cur) =>{ if(!pre.includes(cur)){ pre.push(cur) } return pre;},[])console.log(arrResult)//结果:[“name”, “age”, “long”, “short”]分析: 这里主要是借助迭代功能实现数组的扩展,判断当前元素是否已经添加到数组中,如果不存在就从尾部添加,这个方法在去重方法中应该算比较简单高效的。对对象的属性求和let person = [ { name: ‘xiaoming’, age: 18 },{ name: ‘xiaohong’, age: 17 },{ name: ‘xiaogang’, age: 19 }]let result = person.reduce((a,b) =>{ a = a + b.age; return a;},0)console.log(result)//结果:54分析: 这里主要就是利用reduce第一个参数是迭代,可以通过初始化这个参数的数据类型,达到想实现的效果。总结 使用reduce操作数组时,最重要的就是理解第一个参数是怎么迭代的,可以好好利用初始化这个参数的数据类型来减少很多不必要的代码。上面举的三个高级应用的例子都是利用了这个优点,当然,reduce还有更多的应用,后面碰到还会进行补充的。 如果觉得有用就给个赞吧~ ...

December 18, 2018 · 1 min · jiezi

遍历方法

有用到object对象的转换成数组,然后又想到了遍历方法,所以,也想记录下1. 终止或者跳出循环break跳出循环体,所在循环体已结束continue跳出本次循环,进行下一次循环,所在的循环体未结束return 终止函数执行for (let i = 0; i < 5; i++) { if (i == 3) break; console.log(“The number is " + i); /* 只输出 0 , 1 , 2 , 到3就跳出循环了 /}for (let i = 0; i <= 5; i++) { if (i == 3) continue; console.log(“The number is " + i); / 不输出3,因为continue跳过了,直接进入下一次循环 /}2.遍历方法假数据const temporaryArray = [6,2,3,4,5,1,1,2,3,4,5];const objectArray = [ { id: 1, name: ’d’ }, { id: 2, name: ’d’ }, { id: 3, name: ‘c’ }, { id: 1, name: ‘a’ }];const temporaryObject = { a: 1, b: 2, c: 3, d: 4,};const length = temporaryArray.length;普通for循环遍历for(let i = 0; i < length; i++) { console.log(temporaryArray[i]);}for in 循环/ for in 循环主要用于遍历普通对象,* 当用它来遍历数组时候,也能达到同样的效果,* 但是这是有风险的,因为 i 输出为字符串形式,而不是数组需要的数字下标,* 这意味着在某些情况下,会发生字符串运算,导致数据错误* /for(let i in temporaryObject) { / hasOwnProperty只加载自身属性 / if(temporaryObject.hasOwnProperty(i)) { console.log(temporaryObject[i]); }}for of 循环,用于遍历可迭代的对象for(let i of temporaryArray) { console.log(i);}forEach 第一个值为数组当前索引的值,第二个为索引值,只能遍历数组,无返回值,也无法跳出循环let a = temporaryArray.forEach(function(item, index) { console.log(index, item);});map 返回新数组,只能遍历数组temporaryArray.map(function(item) { console.log(item);});filter 是数组的内置对象,不改变原数组,有返回值temporaryArray.filter(function(item) { console.log(item%2 == 0);});some判断是否有符合的值let newArray = temporaryArray.some(function(item) { return item > 1;});console.log(newArray);every判断数组里的值是否全部符合条件let newArray1 = temporaryArray.every(function(item) { return item > 6;});console.log(newArray1);reduce(function(accumulator, currentValue, currentIndex, array) {}, initValue)accumulator:初始值或者累加计算结束后的返回值, currentValue遍历时的当前元素值,currentIndex当前索引值,array当前数组initValue为初始值,若不添加参数initValue,则accumulator为当前数组的第一个元素值,若添加,则accumulator为initValue值,累加器accumulator从initValue开始运算let temporaryObject3 = {};let newArray2 = objectArray.reduce(function(countArray, currentValue) { / 利用temporaryObject3里存放id来判断原数组里的对象是否相同,若id相同,则继续下一步,不同则将该对象放入新数组中 * 则countArray为去重后的数组 * */ temporaryObject3[currentValue.id] ? ’’ : temporaryObject3[currentValue.id] = true && countArray.push(currentValue); return countArray;}, []);console.log(newArray2);正在努力学习中,若对你的学习有帮助,留下你的印记呗(点个赞咯^_^)往期好文推荐:判断ios和Android及PC端实现文字的省略号css实现波浪线及立方体 ...

October 25, 2018 · 1 min · jiezi