javascript数组的reduce()与reduceRight()方法
javascript数组的reduce()与reduceRight()方法
reduce()方法
- 按照数组元素的先后顺序(按索引从小到大的顺序),分别对数组元素执行一次由程序员提供的回调函数(这个回调函数被称作reducer函数);
- 每一次执行reducer函数时,都会将上一次reducer函数的执行结果作为参数传入;
- 第一次执行reducer函数时不存在上一次的返回结果;
- 如果需要reducer函数从索引为0的元素开始执行,则需要传递初始值,否则索引为0的元素将被作为初始值,索引为1的元素作为第一轮执行reducer函数的元素。
- 如果数组为空且未指定初始值 initialValue,则会抛出
TypeError
。 reduce
不会直接改变调用它的对象,但对象可被调用的 callbackfn 所改变。- 遍历的元素范围是在第一次调用 callbackfn 之前确定的。所以即使有元素在调用开始后被追加到数组中,这些元素也不会被 callbackfn 访问。如果数组现有的元素发生了变化,传递给 callbackfn 的值将会是元素被
reduce
访问时的值(即发生变化后的值); - 在调用
reduce
开始后,尚未被访问的元素若被删除,则其将不会被reduce
访问。 - 如果数组仅有一个元素,并且没有提供初始值 initialValue,或者有提供 initialValue 但是数组为空,那么此唯一值将被返回且
callbackfn
不会被执行。
// 定义一个回调函数以备调用 const getMax=(a, b)=>Math.max(a,b); // 1.为reduce方法指定初始值时,回调函数从数组索引为0的元素开始调用 [1, 100].reduce(getMax, 50);//100 调用两次 [50].reduce(getMax,10);//50 调用一次 // 2. 没有为reduce方法指定初始值 [1, 100].reduce(getMax);//100 调用一次 [50].reduce(getMax);//50 没有调用 直接返回值 [].reduce(getMax);//TypeError // 3.为reduce方法指定初始值,但是数组为空数组 [].reduce(getMax,1);//1 没有调用 直接返回值
示例一、统计元素出现的次数
说明:写一个函数,接收两个参数,一个是数组,一个是需要统计的元素,需要返回这个元素在数组中出现的次数。
/*
这个例子中需要用num与数组中的所有元素做比较,所以reducer函数要从索引为0的数组元素开始执行;
因此要在第一次执行时要传递初始值。
*/
//定义数组 let numbers=[1,2,3,4,2,1,3,5,2,5,3,1,3]; //定义函数 function countEle(array, num){ let result=array.reduce(function(pre, cur){ return pre+=cur==num?1:0; }, 0); return console.log(result); } //调用函数 countEle(numbers, 2);
示例二、返回数组中的最大值
说明:数组的元素都是数字;定义一个reducer函数并使用它
//定义数组 let arr=[1,45,2,53,654,643,64,345,6453,345]; // 定义reducer函数 //由于只需要比较数组中的所有元素,故不需要为reduce方法传入初始值 function maxNum(pre, cur){ return pre>cur?pre:cur; } //使用reduce方法调用reducer函数得到最大值 let result=arr.reduce(maxNum); console.log(result);
示例三、获取价格最高的商品
描述:有一组商品的信息的数组,找到产品价格价格最高的那个产品的信息并返回。
// 取价格最高的商品, let cart = [ { name: "iphone", price: 12000 }, { name: "imac", price: 25000 }, { name: "ipad", price: 3600 } ]; // 定义一个函数,getExpensive(),接收产品信息数组; //由于需要将所有产品的价格都做比较,所以需要为reduce方法传递初始值。 function getExpensive(array){ return array.reduce(function(pre,cur){ return pre=pre.price>cur.price?pre:cur; },{}); } console.log(getExpensive(cart));
示例四、计算购物车中商品的总价
描述:有一组商品的信息的数组,找到产品价格价格最高的那个产品的信息并返回。
// 计算购物车中的商品总价 let cart = [ { name: "iphone", price: 12000 }, { name: "imac", price: 25000 }, { name: "ipad", price: 3600 } ]; const total=cart.reduce((total, curr)=>total+=curr.price,0); console.log(total);//40600
示例五、将二维数组转换为一维数组
// 将二维数组转化为一维数组 let flattened=[[0,1],[2,3],[4,5]]; // let result=flattened.reduce(function(pre, cur){ // return pre.concat(cur); // },[]); let result=flattened.reduce((pre,cur)=>pre.concat(cur),[]); console.log(flattened); console.log(result);
示例六、统计数组中每个元素出现的次数
说明:数组中有相同的元素。
// 计算数组中每个元素出现的次数 let names = ['Alice', 'Tiff', 'Bruce', 'Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'] // 思路:需要传入初始值,因为每个数组元素都要统计在内;比较适合以对象的形式存储结果。 let result=names.reduce((pre, cur)=>{ if(cur in pre){//in运算符:如果指定的属性在指定的对象或其原型链中,则 in 运算符返回 true pre[cur]++; }else{ pre[cur]=1; } return pre; },{}); console.log(result);
示例七、按属性值对object分类
说明:有一些人的信息,按照年龄将这些人分组后存入对象
// 按属性值对object分类 // 有个组数,里面存的是多个人的数据,包括姓名和年龄,希望按照年龄大小归类数据 let people=[ {name:'Alice', age:21}, {name:'Max', age:20}, {name:'Jane', age:20}, ]; // 定义处理函数 function groupBy(data, property){ /* 思路,使用reduce方法,遍历data中的每一个元素,因此为reduce方法赋初始值为一个对象 初始值时空对象,对每一个元素使用reducer函数时,先看看对象中有没有与当前元素的property相同的属性 如果有,则将当前元素push到此属性数组中,如果没有,那么为对象添加此属性并往属性值中push当前元素 */ return data.reduce((pre, cur)=>{ // 每次执行此reducer函数,都要将当前元素中property的值与目标返回对象作比较 let key=cur[property]; //假如返回对象中没有当前元素年龄值得属性 if(!pre[key]){ pre[key]=[]; } // 这里不是二选一,所以不能用if else. pre[key].push(cur); return pre; },{}); } // 调用函数并输出结果 console.log(groupBy(people, 'age'));
示例八、数组去重