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实现3D球状标签云示例代码
Dec 01 Javascript
为什么Node.js会这么火呢?Node.js流行的原因
Dec 01 Javascript
javascript函数命名的三种方式及区别介绍
Mar 22 Javascript
JS作用域深度解析
Dec 29 Javascript
使用jQuery的load方法设计动态加载及解决被加载页面js失效问题
Mar 01 Javascript
Vue 过渡实现轮播图效果
Mar 27 Javascript
微信小程序自定义导航隐藏和显示功能
Jun 13 Javascript
Angularjs中ng-repeat的简单实例
Aug 25 Javascript
原生js实现移动端触摸轮播的示例代码
Dec 22 Javascript
对node通过fs模块判断文件是否是文件夹的实例讲解
Jun 10 Javascript
写给新手同学的vuex快速上手指北小结
Apr 14 Javascript
全面解析JavaScript Module模式
Jul 24 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
php csv操作类代码
2009/12/14 PHP
php开发过程中关于继承的使用方法分享
2011/06/17 PHP
解析dedeCMS验证码的实现代码
2013/06/07 PHP
PHP整数取余返回负数的相关解决方法
2014/05/15 PHP
Codeigniter框架实现获取分页数据和总条数的方法
2014/12/05 PHP
总结PHP中数值计算的注意事项
2016/08/14 PHP
PHP基于DOM创建xml文档的方法示例
2017/02/08 PHP
当前页禁止复制粘贴截屏代码小集
2013/07/24 Javascript
jquery实现兼容浏览器的图片上传本地预览功能
2013/10/14 Javascript
JS获得浏览器版本和操作系统版本的例子
2014/05/13 Javascript
js去字符串前后空格的实现方法
2016/02/26 Javascript
JS动态计算移动端rem的解决方案
2016/10/14 Javascript
Angular2安装angular-cli
2017/05/21 Javascript
JS简单实现数组去重的方法分析
2017/10/14 Javascript
解决iview多表头动态更改列元素发生的错误的方法
2018/11/02 Javascript
javascript 对象 与 prototype 原型用法实例分析
2019/11/11 Javascript
微信小程序利用button控制条件标签的变量问题
2020/03/15 Javascript
vue+ElementUI 关闭对话框清空验证,清除form表单的操作
2020/08/06 Javascript
vue-axios同时请求多个接口 等所有接口全部加载完成再处理操作
2020/11/09 Javascript
[01:09]DOTA2次级职业联赛 - ishow.HMM战队宣传片
2014/12/01 DOTA
[37:29]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第二场 11.19
2020/11/19 DOTA
Python使用cx_Oracle模块将oracle中数据导出到csv文件的方法
2015/05/16 Python
Python简单实现阿拉伯数字和罗马数字的互相转换功能示例
2018/04/17 Python
推荐技术人员一款Python开源库(造数据神器)
2020/07/08 Python
瑞士设计师家具和家居饰品网上商店:Bruno Wickart
2019/03/18 全球购物
广州御银科技股份有限公司试卷(C++)
2016/11/04 面试题
秋季运动会活动方案
2014/02/05 职场文书
创建青年文明号材料
2014/05/09 职场文书
应聘教师求职信
2014/07/19 职场文书
房屋认购协议书
2015/01/29 职场文书
单位更名证明
2015/06/18 职场文书
2015年高三年级组工作总结
2015/07/21 职场文书
PyTorch中的torch.cat简单介绍
2022/03/17 Python
【海涛七七解说】DCG第二周:DK VS 天禄
2022/04/01 DOTA
golang的文件创建及读写操作
2022/04/14 Golang
IDEA中sout快捷键无效问题的解决方法
2022/07/23 Java/Android