JS40 reduce方法

数组的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可以代替mapfilter返回筛选过的数组

返回数组中乘以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
}, {})

参考

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值