数组的reduce()
方法接受一个函数作为累加器,将数组的每个值从左到右开始用该函数进行处理,最终输出为一个值
不会改变原数组
语法:
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
其中参数:
total
:初始值或者计算后的返回值,必须currentValue
:当前元素,必须currentIndex
:当前元素索引,可选arr
:当前数组,可选initialValue
:传递给函数的舒初始值,可选
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15
reduce
的用途很多,关键点在于initialValue
传入的值,可以是不同的类型
提前结束
reduce
方法是没有办法使用break
提前结束循环的,但是可以通过修改遍历函数的第四个参数arr
来变相的提前结束循环
注意,由于arr
是对原数组的引用,为了防止到原数组造成的印象,引用reduce
的数组最好是原数组的拷贝
假设我们运行到第i
项需要提前结束遍历,只需将arr
修改arr.splice(i + 1)
即可(或者arr = arr.slice(0, i+1)
[...originArr].reduce((total, current, currentIndex, arr) => {
// 提前结束的逻辑判断
if (total > 100) {
arr.splice(currentInde + 1)
return 100;
}
}), '')
求和
最常见的用法就是数组求和:
let obj = {length: 100}
let arr = Array.from(obj, (val, index) => index +1 )
let reducer = (total, currentValue, currentIndex, arr) => {
console.log('total', total);
console.log('currentValue', currentValue);
console.log('currentIndex', currentIndex);
console.log('arr', arr);
return total + currentValue
}
console.log(arr.reduce(reducer, 100))
console.log(arr.reduce(reducer))
console.log(arr)
返回筛选过的数组
reduce
可以代替map
和filter
返回筛选过的数组
返回数组中乘以2后大于50的成员,组成一个新的数组
const numbers = [10, 20, 30, 40];
let result = numbers.reduce((finalArr, currentVal) => {
currentVal = currentVal * 2;
if (currentVal > 50) {
finalArr.push(currentVal)
}
return finalArr
}, [])
检测括号是否对其封闭
思路就是将字符串转换为数组,然后给定一个初始变量0, 遇到(
就加1,遇到)
就减1
,最后判断是否为0
// 2 使用 reduce 检测括号是否对齐封闭
const isBracketBalanced = string = > {
const tempArr = string.split('');
const isBalanced = tempArr.reduce((flag, currentVal) = > {
// 如果')'先出现
if (flag < 0) {
return flag
}
if (currentVal === '(') {
flag += 1
} else if (currentVal === ')') {
flag -= 1
}
return flag;
}, 0);
return isBalanced === 0 ? 'yes' : 'no';
};
console.log(isBracketBalanced('(())')); // yes
console.log(isBracketBalanced('(hello)')); // yes
console.log(isBracketBalanced('(()')); // no
console.log(isBracketBalanced(')(')); // no
判断数组中有多少个重复项
计算数组中每个值的重复数量,并输出一个对象来展示:
// 3 使用reduce判断数组中有多少个重复项
const cars = ['BMW', 'Benz', 'Benz', 'Tesla', 'BMW', 'Toyota'];
const findRepeat = arr => {
return arr.reduce((obj, currentVal) = > {
if (!obj[currentVal]) {
obj[currentVal] = 1
} else {
obj[currentVal] += 1
}
return obj
}, {})
};
console.log(findRepeat(cars)); // {BMW: 2, Benz: 2, Tesla: 1, Toyota: 1}
将多层数组转换成一层数组
const nestedArr = [1, 2, [3, 4, [5, 6]]];
const flatten = arr => arr.reduce(
(total, currentVal) => total.concat(Array.isArray(currentVal) ? flatten(currentVal) : currentVal), []);
console.log(flatten(nestedArr))
将下面数组转成对象,key/value 对应里层数组的两个值
const objLikeArr = [["name", "Jim"], ["age", 18], ["single", true]];
const makeObj = arr => arr.reduce(
(obj, currentVal) => {
obj[currentVal[0]] = currentVal[1];
return obj;
}, {});
console.log(makeObj(objLikeArr))
对数组进行分组:
const arr = [{
"name": "jim",
"color": "blue",
"age": "22"
}, {
"name": "Sam",
"color": "blue",
"age": "33"
}, {
"name": "eddie",
"color": "green",
"age": "77"
}, {
"name": "joe",
"color": "yellow",
"age": "44"
}];
const groupByReduce = (arr, name) => arr.reduce((obj, currentVal) => {
const key = currentVal[name];
obj[key] = obj[key] || [];
obj[key].push(currentVal);
return obj
}, {});
console.log(groupByReduce(arr, 'color'));
// {blue: Array(2), green: Array(1), yellow: Array(1)}
对象俺属性名排序:
const sortObject = (obj) => Object.keys(obj).sort().reduce((result, currentVal) => {
result[currentVal] = obj[currentVal];
return result
}, {})