数组 reduce 简介及使用场景

(一)reduce的作用

1 . 数组求和,求乘积
2 . 计算数组中每个元素出现的次数
3 . 数组去重
4 . 数组扁平化(将二维,或者多维数组转化为一维数组)
等等等等…基本上数组方法能做的事情,reduce都能做

大部分现代的数组方法都返回一个新的数组,而 Array.reduce() 更加灵活。它可以返回任意值,它的功能就是将一个数组的内容聚合成单个值。这个值可以是数字、字符串,甚至可以是对象或新数组

(二)reduce的参数

reduce的参数,只接收两个参数,1. 回调函数(必填)2. initValue 初始值(非必填)
注意:回调函数有四个参数

对空数组调用reduce()和reduceRight()是不会执行其回调函数的,可认为reduce()对空数组无效

1 . Accumulator (累计器),上一次回调函数的返回值,如果有initValue,他就表示为initValue的值
2 . Current Value 当前正在处理的数组元素
3 . Current Index 当前正在处理的数组元素的索引,如果提供了initValue ,则索引值为0,否则索引值为1
4 . Source Array 源数组

const numArr = [1, 2, 3, 4, 5]
const sum = numArr.reduce(function (accumulator, currentValue, currentIndex, array) {
  console.log(accumulator, currentValue)
  return accumulator + currentValue;
})
// 这里因为没有init值,所以输出,1 2(没有init时,循环 length - 1 次)
const numArr = [1, 2, 3, 4, 5]
const sum = numArr.reduce(function (accumulator, currentValue, currentIndex, array) {
  console.log(accumulator, currentValue)
  return accumulator + currentValue;
}, 5)
// 这里因为有init值,所以输出,5 1(有init时,循环 length 次)

(三)利用reduce,求数组内所有元素的和,积 ,最大值,最小值

求和

const numArr = [1, 2, 3, 4, 5]
const sum = numArr.reduce((pre, cur, index, arr) => {
  return pre + cur
})

// 封装成函数
function Accumulation(val) {
  return val.reduce((pre, cur) => pre + cur);
}
console.log(Accumulation(numArr)) // 15

求积(跟求和一样,就是把 + 换成 *

const numArr = [1, 2, 3, 4, 5]
const sum = numArr.reduce((pre, cur, index, arr) => {
  return pre * cur
})

// 封装成函数
function Multiplication(val) {
  return val.reduce((pre, cur) => pre * cur);
}
console.log(Multiplication(numArr)) // 120

求最大值

const numArr = [12, 45, 21, 65, 38, 76, 108, 43];

function maxNum(arr = []) {
  return arr.reduce((pre, cur) => pre > cur ? pre : cur)
}

求最小值

const numArr = [12, 45, 21, 65, 38, 76, 108, 43];

function maxNum(arr = []) {
  return arr.reduce((pre, cur) => pre < cur ? pre : cur)
}

(四)利用reduce,计算数组中每个元素出现的次数

const nameArr = ['佩可莉姆', '可可萝', '凯露', '可可萝', '真步', '佩可莉姆', '可可萝']
// 设置一个初始值,init为空对象{}
const sum = nameArr.reduce((pre, cur, index, arr) => {
  // 如果:当前值在上次的返回值中,则让他的value值++
  // pre[cur] 相当于 obj.key 
  if (cur in pre) {
    pre[cur]++
  }
  // 否则: pre[cur] = 1 的意思类比于 obj.key = value
  // 因为这是 else 的值,这个 key,肯定不在这个对象中,如果一个对象的不存在这个 key ,我们又用obj.key的形式声明
  // 则会直接给该对象添加属性,并赋值
  else {
    pre[cur] = 1
  }
  return pre;
}, {})
// { 佩可莉姆: 2, 可可萝: 3, 凯露: 1, 真步: 1 }

// 封装成函数
function Count(arr = []) {
  return arr.reduce((pre, cur) => (pre[cur] = (pre[cur] || 0) + 1, pre), {});
}

如果你看不懂封装成函数的这段代码,下面是解释

1 . 逗号表达式(逗号运算符)逗号运算符是二元运算符,它能够先执行运算符左侧的操作数,然后再执行右侧的操作数,最后返回最右侧操作数的值。
举个例子:
与条件运算符、逻辑运算符根据条件来决定是否执行所有或特定操作数不同,逗号运算符会执行所有的操作数,但不会返回所有操作数的结果,它只返回最后一个操作数的值。(也就是例子中的 x * 8)

const exampleNum = (x = 5 + 3, x = x - 4, x * 8)
console.log(exampleNum) // 32
const nameArr = ['佩可莉姆', '可可萝', '凯露', '可可萝', '真步', '佩可莉姆', '可可萝']
// 封装成函数
function Count(arr = []) {
  // 第一次循环 pre = {},cur = '佩可莉姆'
  // 第二次循环 pre = { '佩可莉姆':1 } , cur = '可可萝'
  // 第三次循环同理 结束时 pre = { '佩可莉姆':1 , '可可萝':1, '凯露':1}
  // 第四次循环 开始时 pre = { '佩可莉姆':1 , '可可萝':1, '凯露':1}
  return arr.reduce((pre, cur) => (
    // 第一次循环 {}.佩可莉姆 = {}.佩可莉姆 || 0 因为此时,{}.佩可莉姆 = undefined 所以这里 = 0 + 1
    // 然后返回 pre 也就是 { '佩可莉姆':1 }

    // 第二次循环 { '佩可莉姆':1 }.可可萝 = { '佩可莉姆':1 }.可可萝 || 0,同理 { '佩可莉姆':1 }.可可萝 = undefined,所以这里 = 0 + 1
    // 然后返回 pre 也就是 { '佩可莉姆':1 , '可可萝':1}

    // 第四次循环 { '佩可莉姆':1 , '可可萝':1, '凯露':1}.可可萝 = { '佩可莉姆':1 , '可可萝':1, '凯露':1}.可可萝 || 0 ,
    // 这时 { '佩可莉姆':1 , '可可萝':1, '凯露':1}.可可萝 = 1 已经有值了,不会走||运算了,之后再 + 1 
    // 然后返回 pre 也就是 { '佩可莉姆':1 , '可可萝':2, '凯露':1 }
    pre[cur] = (pre[cur] || 0) + 1, pre
  ), {});
}

(五)数组扁平化

Array.concat()可以传入数组,也可以传入值
(数组扁平化Array.flat(Infinity)数组自带扁平化的方法,但是兼容性不太好,IE浏览器更是一点都不兼容,但是新版本的IE(Edge)却可以完美支持)

const numArr = [1, [2, [3, [4, [5]]]], 6]

const newArr = (arr) => {
  return arr.reduce((pre, cur) => {
    return pre.concat(Array.isArray(cur) ? newArr(cur) : cur)
  }, [])
}

// 封装成函数
function myFlat(arr = []) {
  return arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? myFlat(cur) : cur), [])
}

(六)数组去重

const nameArr = ['佩可莉姆', '可可萝', '凯露', '可可萝', '真步', '佩可莉姆', '可可萝']

function myUnique(arr = []) {
  return arr.reduce((pre, cur) => pre.includes(cur) ? pre : [...pre, cur], [])
}

(七)数组对象去重

const arrObj = [{ name: '小明' }, { name: '小红' }, { name: '小兰' }, { name: '小明' }, { name: '小兰' }];
// 定义一个空对象,用来保存第一次循环的对象的值,第二次时啥也不处理处理
const obj = {};
const newArr = arrObj.reduce((pre, cur, index) => {
  // 将需要去重的字段值作为obj的key,判断obj上是否存在这个key的值,如【小明】这个key,存在则啥也不干,跳过这次循环
  // 进入下次循环,否则,将这个key值设置为true,如obj.小明=true,同时,将这个值push给pre最后返回
  obj[cur.name] ? '' : (obj[cur.name] = true && pre.push(cur));
  return pre;
}, []);

(八)斐波那契数列

存在一个问题,输入小于2的数,都会返回 [0,1],这个问题可以根据自己的情况修改

function myFibonacci(time = 2) {
  const Arr = [...new Array(time).keys()]
  return Arr.reduce((pre, cur, index) => {
    index > 1 && pre.push(pre[index - 1] + pre[index - 2])
    return pre
  }, [0, 1])
}
console.log(myFibonacci(1)) // [0, 1]
console.log(myFibonacci(2)) // [0, 1]
console.log(myFibonacci(10)) // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript 中的数组方法有很多,每个方法都有各自的使用场景。以下是一些常见的数组方法及其使用场景: 1. `push()`:向数组末尾添加一个或多个元素。 使用场景:需要动态向数组中添加元素时。 2. `pop()`:从数组末尾删除一个元素。 使用场景:需要删除数组中最后一个元素时。 3. `unshift()`:向数组开头添加一个或多个元素。 使用场景:需要动态向数组开头添加元素时。 4. `shift()`:从数组开头删除一个元素。 使用场景:需要删除数组中第一个元素时。 5. `splice()`:删除、插入或替换数组中的元素。 使用场景:需要对数组进行复杂的操作时,如删除、插入或替换数组中的元素。 6. `slice()`:截取数组中的一部分元素,返回一个新数组使用场景:需要从数组中获取一个子集时,但不想修改原数组。 7. `concat()`:将多个数组合并成一个新数组使用场景:需要将两个或多个数组合并为一个数组时。 8. `join()`:将数组中的所有元素连接成一个字符串。 使用场景:需要将数组中的元素以特定的方式连接起来时。 9. `indexOf()`:查找数组中某个元素的位置。 使用场景:需要查找数组中某个元素的位置时。 10. `filter()`:返回符合条件的元素组成的新数组使用场景:需要筛选数组中符合某些条件的元素时。 11. `map()`:返回对每个元素进行操作后的数组使用场景:需要对数组中的每个元素进行操作并返回一个新数组时。 12. `reduce()`:使用指定的函数数组中的元素合并为一个值。 使用场景:需要将数组中的元素合并为一个值时,如求和、求乘积等。 以上是一些常见的数组方法及其使用场景,当然还有其他的数组方法,具体使用场景还需根据实际情况进行选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值