reduce函数高级用法

reduce函数高级用法reduce 函数是 ECMAScript6 ES6 中数组的一个迭代方法 它接收一个回调函数作为累加器 accumulator 对该数组的所有元素 从左到右 执行操作 最后将计算结果累积为

大家好,欢迎来到IT知识分享网。

reduce()函数是 ECMAScript 6 (ES6) 中数组的一个迭代方法,它接收一个回调函数作为累加器(accumulator),对该数组的所有元素(从左到右)执行操作,最后将计算结果累积为单一输出值。

reduce 函数是 JavaScript 中的一个功能强大的高阶函数,它算是 JS 数组方法里面较为复杂的一个函数了。reduce 的灵活性在于它能够遍历数组的所有元素,根据提供的函数累积一个最终的返回值。reduce()方法可以应用的场景特别多,循环遍历能做的,reduce都可以做,比如数组求和、数组求积、统计数组中元素出现的次数、数组去重等等。 

一、reduce的用法

reduce() 方法对数组中的每个元素按序执行一个由您提供的 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。

第一次执行回调函数时,不存在“上一次的计算结果”。如果需要回调函数从数组索引为 0 的元素开始执行,则需要传递初始值。否则,数组索引为 0 的元素将被作为初始值 initialValue,迭代器将从第二个元素开始执行(索引为 1 而不是 0)。

注意: reduce() 对于空数组是不会执行回调函数的。

语法如下:

array.reduce(function(total, currentValue, currentIndex, arr), initialValue 

简洁语法:

reduce(callbackFn, initialValue) 

function(total,currentValue, index,arr):回调函数,必需。

  • total:上一次回调函数的返回值,第一次调用回调函数时,如果指定的初始值 initialValue,那么该参数值就是 initialValue,否则就是数组元素的第一个。
  • currentValue:数组中正在处理的元素。在第一次调用时,若指定了初始值 initialValue,那么当前处理的元素就是数组的第一个元素,否则的话就是第二个元素。
  • currentIndex:数组中正在处理的元素的索引。若指定了初始值 initialValue,则起始索引号为 0,否则从索引 1 起始。
  • array:用于遍历的数组。

initialValue:可选。传递给函数的初始值。也就是第一次调用回调函数时参数total,是否指定初始值将会影响其它几个参数的值。

reduce 方法的返回值就是遍历所有数组执行回调函数后的返回值。

二、reduce的使用场景

2.1 数组求和

日常开发基本使用中,最简单其实就是数组求和的场景了。代码如下:

const arr = [1, 2, 3, 4, 5, 6, 7, 8]; const result = arr.reduce((total, currentValue) => {     return total + currentValue; }, 0); console.log(result); // 36 

按指定属性求和:

const arr = [     { name: '小明', score: 98 },      { name: '小花', score: 96 },      { name: '小强', score: 90 },  ]; const result = arr.reduce((total, currentValue) => {      return total + currentValue.score }, 0); console.log(result); // 284 

按照条件求和:

const arr = [     { name: '张三', score: 93 },      { name: '李四', score: 76 },      { name: '王五', score: 80 },      { name: '赵六', score: 65 },  ]; const result = arr.reduce((total, currentValue) => {      return currentValue.score >= 80 ? total + currentValue.score : total; }, 0); console.log(result); // 173 

2.2 计算数组每个数据出现的次数

这种场景通常出现在算法题当中,借助 reduce 就可以简单实现它。其主要思路是通过键值对的形式巧妙的将出现的次数存储下来。

代码如下:

const arr = ['Allice', 'Bob', 'Tiff', 'Bruce', 'Bob', 'Jack', 'Allice', 'Bob']; const result = arr.reduce((total, currentValue) => {     total[currentValue] = (total[currentValue] || 0) + 1;     return total; }, {}); console.log(result); // {Allice: 2, Bob: 3, Tiff: 1, Bruce: 1, Jack: 1} 

变形:

同样的道理,也可以统计字符串中每个字符的出现次数,只需把字符串使用split方法分割成数组即可。

const str = 'Hello World'; const result = str.split('').reduce((total, currentValue) => {     total[currentValue] = (total[currentValue] || 0) + 1;     return total; }, {}); console.log(result); // {H: 1, e: 1, l: 3, o: 2, " ": 1, d: 1, r: 1, W: 1

2.3 数组去重

想不到吧!reduce还能实现数组去重?是的!

过程如下:

  1. 初始化一个空数组;
  2. 将需要去重处理的数组中的第1项在初始化数组中查找,如果找不到(空数组中肯定找不到),就将该项添加到初始化数组中;
  3. 将需要去重处理的数组中的第2项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中;
  4. ……;
  5. 将需要去重处理的数组中的第n项在初始化数组中查找,如果找不到,就将该项继续添加到初始化数组中;
  6. 将这个初始化数组返回。

代码如下:

const arr = [1, 2, 2, 3, 3, 4, 4, 5, 6]; const result = arr.reduce((total, currentValue) => {     if(!total.includes(currentValue)) {         total.push(currentValue)     }     return total; }, []); console.log(result); // [1, 2, 3, 4, 5, 6] 

2.4 数组扁平化

将初始值设置为了空数组,然后利用 concat 将数组中的每一项与初始值拼接,得到一个新的数组。

const arr = [['a', 'b'], ['c', 'd'], ['e', 'f']]; const result = arr.reduce((total, currentValue) => {     return total.concat(currentValue); }, []); console.log(result); // ['a', 'b', 'c', 'd', 'e', 'f'] 

2.5 将二维数组转为对象

又没想到吧!将二维数组转化为对象,其过程为将初始值设置为了空对象,currentValue可以看做为[key, value],然后total[key] = value把键值放入total对象中。

const arr = [['name', '张三'], ['age', '30'], ['sex', '男']]; const result = arr.reduce((total, [key, value]) => {     total[key] = value     return total; }, {}); console.log(result); // {name: '张三', age: '30', sex: '男'} 

2.6 提取数组中的特定值生产新数组

const arr = [{id: 1, name: 'Tom'}, { id: 2, name: 'Jack' }, { id: 3, name: 'Anna' }] const result = arr.reduce((total, currentValue) => {      return [...total, currentValue.name] }, []); console.log(result); // ['Tom', 'Jack', 'Anna'] 

2.7 合并数组对象

const arr = [{name: '张三'}, { age: 30 }, { sex: '男' }]; const result = arr.reduce((total, currentValue) => {      return { ...total, ...currentValue } }, {}); console.log(result); // {name: '张三', age: 30, sex: '男'}

2.8 解析url参数

const url = 'https://www.csdn.com/index.html?name=lvbin&id=666666&latitude=31.101109&longitude=121.51367';
const params = url.split('?')[1];
const result = params.split('&').reduce((total, currentValue) => { 
    const [key, value] = currentValue.split('=');
    total[key] = value;
    return total;
}, {});
console.log(result); 
// {name: 'lvbin', id: '666666', latitude: '31.101109', longitude: '121.51367'}

2.9 反序列化参数

const stringifyData = (data = {}) => {
    return Object.entries(data).reduce((total, currentValue) => {
        return `${total}${currentValue[0]}=${encodeURIComponent(currentValue[1])}&`
    }, Object.keys(data).length ? "?" : "")
    .replace(/&$/, "");
};
const params = stringifyData({
    name: "Jack",
    id: '123456',
    age: 18
});
const url = `https://www.test.com/index.html${params}`;
console.log(url);
// https://www.test.com/index.html?name=Jack&id=123456&age=18

2.10 求最大值、最小值

计算数组中的最大值或最小值,可以使用原生api Math.max()和Math.min(),当然我们也可以使用reduce来实现。

const array = [1, 10, 6, 8, 3, 9]; const max = array.reduce((max, num) => (max > num ? max : num)); console.log(max); // 10 const min = array.reduce((min, num) => (min < num ? min : num)); console.log(min); // 1 

2.11 根据指定项分组

const arr = [     { name: '小明', score: 96 },     { name: '小华', score: 88 },     { name: '小红', score: 92 },     { name: '小刚', score: 100 },     { name: '小李', score: 96 },     { name: '小美', score: 90 },     { name: '小芳', score: 100 }, ] const result = arr.reduce((total, currentValue) => {     const { score } = currentValue;     if(!total[score]) total[score] = [];     total[score].push(currentValue)     return total; }, {}) console.log(result) //{"88":[{"name":"小华","score":88}],"90":[{"name":"小美","score":90}],"92":[{"name":"小红","score":92}],"96":[{"name":"小明","score":96},{"name":"小李","score":96}],"100":[{"name":"小刚","score":100},{"name":"小芳","score":100}]}

更复杂场景,多条件数据分类。

假设有一个包含人员信息的数组,每个人员对象有 age 和 gender 属性。现在我们想要根据人员的年龄和性别进行多条件分类。

const arr = [   { name: 'Alice', age: 25, gender: 'female' },   { name: 'Bob', age: 30, gender: 'male' },   { name: 'Charlie', age: 25, gender: 'male' },   { name: 'Dave', age: 35, gender: 'male' },   { name: 'Eve', age: 25, gender: 'female' }, ]; const result = arr.reduce((accumulator, person) => {     const { age, gender } = person;     if (!accumulator[age]) {         accumulator[age] = {};     }     if (!accumulator[age][gender]) {         accumulator[age][gender] = [];     }     accumulator[age][gender].push(person);     return accumulator; }, {}); console.log(result); //{"25":{"female":[{"name":"Alice","age":25,"gender":"female"},{"name":"Eve","age":25,"gender":"female"}],"male":[{"name":"Charlie","age":25,"gender":"male"}]},"30":{"male":[{"name":"Bob","age":30,"gender":"male"}]},"35":{"male":[{"name":"Dave","age":35,"gender":"male"}]}}

2.12 管道函数

当结合其他高阶用法时,reduce 可以应用于非常复杂的场景。其中一个非常复杂的场景是实现函数组合或管道。管道(Pipe)是指输入一个值,依次经过管道(有序的函数运算)后输出这个值,也是函数编程的核心思想。

函数组合是一种将多个函数合并成一个新函数的技术,其中每个函数的输出都是下一个函数的输入。我们可以使用 reduce 和函数组合技术来实现函数管道,将一系列函数应用于数据并依次传递结果。

function add10(num) {   return num + 10; }; function multipl2(num) {   return num * 2; }; function divide3(num) {   return num / 3; }; const compose = (fns) => (initialValue) => fns.reduce((previous, current) => current(previous), initialValue); const calculate1 = compose([add10, divide3]); const calculate2 = compose([divide3, add10, multipl2]); // 先加10,在除以3 console.log(calculate1(20)); //10 // 先加10,在除以3,最后乘以2 console.log(calculate2(9)); //26

三、总结

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

reduce除了以上介绍的使用场景外,还有很多其它使用场景,有兴趣的朋友可以研究一下。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/117186.html

(0)
上一篇 2025-11-23 08:00
下一篇 2025-11-23 08:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信