JavaScript中reduce()的用法


Posted in Javascript onMay 11, 2022

前言

过去有很长一段时间,我一直很难理解 reduce() 这个方法的具体用法,平时也很少用到它。事实上,如果你能真正了解它的话,其实在很多地方我们都可以用得上,那么今天我们就来简单聊聊JS中 reduce() 的用法。

一、语法

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

其中,

  • arr 表示原数组;
  • prev 表示上一次调用回调时的返回值,或者初始值 init;
  • cur 表示当前正在处理的数组元素;
  • index 表示当前正在处理的数组元素的索引,若提供 init 值,则索引为0,否则索引为1;
  • init 表示初始值。

看上去是不是感觉很复杂?没关系,只是看起来而已,其实常用的参数只有两个:prev 和 cur。接下来我们跟着实例来看看具体用法吧~

二、实例

先提供一个原始数组:

var arr = [3,9,4,3,6,0,9];

实现以下需求的方式有很多,其中就包含使用reduce()的求解方式,也算是实现起来比较简洁的一种吧。

1. 求数组项之和

var sum = arr.reduce(function (prev, cur) {
    return prev + cur;
},0);

由于传入了初始值0,所以开始时prev的值为0,cur的值为数组第一项3,相加之后返回值为3作为下一轮回调的prev值,然后再继续与下一个数组项相加,以此类推,直至完成所有数组项的和并返回。

2. 求数组项最大值

var max = arr.reduce(function (prev, cur) {
    return Math.max(prev,cur);
});

由于未传入初始值,所以开始时prev的值为数组第一项3,cur的值为数组第二项9,取两值最大值后继续进入下一轮回调。

3. 数组去重

var newArr = arr.reduce(function (prev, cur) {
    prev.indexOf(cur) === -1 && prev.push(cur);
    return prev;
},[]);

实现的基本原理如下:

① 初始化一个空数组

② 将需要去重处理的数组中的第1项在初始化数组中查找,如果找不到(空数组中肯定找不到),就将该项添加到初始化数组中

③ 将需要去重处理的数组中的第2项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中

④ ……

⑤ 将需要去重处理的数组中的第n项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中

⑥ 将这个初始化数组返回

三、其他相关方法

1. reduceRight()

该方法用法与reduce()其实是相同的,只是遍历的顺序相反,它是从数组的最后一项开始,向前遍历到第一项。

2. forEach()、map()、every()、some()和filter()

详情请戳→简述forEach()、map()、every()、some()和filter()的用法

重点总结:

reduce() 是数组的归并方法,与forEach()、map()、filter()等迭代方法一样都会对数组每一项进行遍历,但是reduce() 可同时将前面数组项遍历产生的结果与当前遍历项进行运算,这一点是其他迭代方法无法企及的

先看w3c语法

array.reduce(function(total, currentValue, currentIndex, arr), initialValue);
/*
  total: 必需。初始值, 或者计算结束后的返回值。
  currentValue: 必需。当前元素。
  currentIndex: 可选。当前元素的索引;                     
  arr: 可选。当前元素所属的数组对象。
  initialValue: 可选。传递给函数的初始值,相当于total的初始值。
*/

常见用法

数组求和

const arr = [12, 34, 23];
const sum = arr.reduce((total, num) => total + num);
<!-- 设定初始值求和 -->
const arr = [12, 34, 23];
const sum = arr.reduce((total, num) => total + num, 10);  // 以10为初始值求和
<!-- 对象数组求和 -->
var result = [
  { subject: 'math', score: 88 },
  { subject: 'chinese', score: 95 },
  { subject: 'english', score: 80 }
];
const sum = result.reduce((accumulator, cur) => accumulator + cur.score, 0); 
const sum = result.reduce((accumulator, cur) => accumulator + cur.score, -10);  // 总分扣除10分

数组最大值

const a = [23,123,342,12];
const max = a.reduce(function(pre,cur,inde,arr){return pre>cur?pre:cur;}); // 342

进阶用法

数组对象中的用法

<!-- 比如生成“老大、老二和老三” -->
const objArr = [{name: '老大'}, {name: '老二'}, {name: '老三'}];
const res = objArr.reduce((pre, cur, index, arr) => {
  if (index === 0) {
    return cur.name;
  }
  else if (index === (arr.length - 1)) {
    return pre + '和' + cur.name;
  }
  else {
    return pre + '、' + cur.name;
  }
}, '');

求字符串中字母出现的次数

const str = 'sfhjasfjgfasjuwqrqadqeiqsajsdaiwqdaklldflas-cmxzmnha';
const res = str.split('').reduce((accumulator, cur) => {accumulator[cur] ? accumulator[cur]++ : accumulator[cur] = 1; return accumulator;}, {});

数组转数组

<!-- 按照一定的规则转成数组 -->
var arr1 = [2, 3, 4, 5, 6]; // 每个值的平方
var newarr = arr1.reduce((accumulator, cur) => {accumulator.push(cur * cur); return accumulator;}, []);

数组转对象

<!-- 按照id 取出stream -->
var streams = [{name: '技术', id: 1}, {name: '设计', id: 2}];
var obj = streams.reduce((accumulator, cur) => {accumulator[cur.id] = cur; return accumulator;}, {});

高级用法

多维的叠加执行操作

<!-- 各科成绩占比重不一样, 求结果 -->
var result = [
  { subject: 'math', score: 88 },
  { subject: 'chinese', score: 95 },
  { subject: 'english', score: 80 }
];
var dis = {
    math: 0.5,
    chinese: 0.3,
    english: 0.2
};
var res = result.reduce((accumulator, cur) => dis[cur.subject] * cur.score + accumulator, 0);
var prices = [{price: 23}, {price: 45}, {price: 56}];
var rates = {
  us: '6.5',
  eu: '7.5',
};
var initialState = {usTotal:0, euTotal: 0};
var res = prices.reduce((accumulator, cur1) => Object.keys(rates).reduce((prev2, cur2) => {
  console.log(accumulator, cur1, prev2, cur2);
  accumulator[`${cur2}Total`] += cur1.price * rates[cur2];
  return accumulator;
}, {}), initialState);

var manageReducers = function() {
  return function(state, item) {
    return Object.keys(rates).reduce((nextState, key) => {
        state[`${key}Total`] += item.price * rates[key];
        return state;
      }, {});
  }
};
var res1= prices.reduce(manageReducers(), initialState);

扁平一个二维数组

var arr = [[1, 2, 8], [3, 4, 9], [5, 6, 10]];
var res = arr.reduce((x, y) => x.concat(y), []);

对象数组去重

const hash = {};
  chatlists = chatlists.reduce((obj, next: Object) => {
    const hashId = `${next.topic}_${next.stream_id}`;
    if (!hash[hashId]) {
      hash[`${next.topic}_${next.stream_id}`] = true;
      obj.push(next);
    }
    return obj;
  }, []);

compose函数

redux compose源码实现

function compose(...funs) {
    if (funs.length === 0) {
        return arg => arg;
    }
    if (funs.length === 1) {
       return funs[0];
    }
    return funs.reduce((a, b) => (...arg) => a(b(...arg)))

}

总结

到此这篇关于JavaScript中reduce()用法实例的文章就介绍到这了!


Tags in this post...

Javascript 相关文章推荐
js 自制滚动条的小例子
Mar 16 Javascript
JS实现的省份级联实例代码
Jun 24 Javascript
jQuery判断checkbox是否选中的3种方法
Aug 12 Javascript
js 加密压缩出现bug解决方案
Nov 25 Javascript
JavaScript转换二进制编码为ASCII码的方法
Apr 16 Javascript
jQuery仅用3行代码实现的显示与隐藏功能完整实例
Oct 08 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单
Nov 25 Javascript
微信小程序进行微信支付的步骤昂述
Dec 01 Javascript
jQuery实现ajax无刷新分页页码控件
Feb 28 Javascript
微信小程序实现获取自己所处位置的经纬度坐标功能示例
Nov 30 Javascript
JS中‘hello’与new String(‘hello’)引出的问题详解
Aug 14 Javascript
详解Axios统一错误处理与后置
Sep 26 Javascript
处理canvas绘制图片模糊问题
介绍一下28个JS常用数组方法
May 06 #Javascript
VUE解决跨域问题Access to XMLHttpRequest at
js判断两个数组相等的5种方法
May 06 #Javascript
vue使用watch监听属性变化
Apr 30 #Vue.js
vue-cli3.x配置全局的scss的时候报错问题及解决
vue项目如何打包之项目打包优化(让打包的js文件变小)
You might like
世界上第一台立体声收音机
2021/03/01 无线电
使用php清除bom示例
2014/03/03 PHP
浅谈PHP中其他类型转化为Bool类型
2016/03/28 PHP
巧妙破除网页右键禁用的十大绝招
2006/08/12 Javascript
JavaScript 联动的无限级封装类,数据采用非Ajax方式,随意添加联动
2010/06/29 Javascript
extjs grid设置某列背景颜色和字体颜色的实现方法
2010/09/06 Javascript
javascript中定义类的方法详解
2015/02/10 Javascript
JS模拟酷狗音乐播放器收缩折叠关闭效果代码
2015/10/29 Javascript
基于javascript实现图片预加载
2016/01/05 Javascript
jQuery树形控件zTree使用小结
2016/08/02 Javascript
老生常谈javascript的类型转换
2016/10/12 Javascript
微信JS-SDK自定义分享功能实例详解【分享给朋友/分享到朋友圈】
2016/11/25 Javascript
浅谈Angular.js中使用$watch监听模型变化
2017/01/10 Javascript
Jquery树插件zTree实现菜单树
2017/01/24 Javascript
网页中的图片查看器viewjs使用方法
2017/07/11 Javascript
基于vue-resource jsonp跨域问题的解决方法
2018/02/03 Javascript
vue根据进入的路由进行原路返回的方法
2018/09/26 Javascript
vue如何在用户要关闭当前网页时弹出提示的实现
2020/05/31 Javascript
JavaScript中while循环的基础使用教程
2020/08/11 Javascript
Python写的Tkinter程序屏幕居中方法
2015/03/10 Python
Python中在for循环中嵌套使用if和else语句的技巧
2016/06/20 Python
Pandas 数据处理,数据清洗详解
2018/07/10 Python
如何通过雪花算法用Python实现一个简单的发号器
2019/07/03 Python
python sitk.show()与imageJ结合使用常见的问题
2020/04/20 Python
python使用QQ邮箱实现自动发送邮件
2020/06/22 Python
Selenium 配置启动项参数的方法
2020/12/04 Python
字符串str除首尾字符外的其他字符按升序排列
2013/03/08 面试题
高三自我鉴定范文
2013/10/19 职场文书
音乐教学反思
2014/02/02 职场文书
护士的自我鉴定
2014/02/07 职场文书
教师群众路线教育实践活动学习笔记
2014/11/05 职场文书
2014年度培训工作总结
2014/11/27 职场文书
普宁寺导游词
2015/02/04 职场文书
社区端午节活动总结
2015/02/11 职场文书
Mysql中 unique列插入重复值该怎么解决呢
2021/05/26 MySQL
MySQL令人大跌眼镜的隐式转换
2021/08/23 MySQL