ES5 —— reduce 方法

        reduce 作为ES5新增的常规数组方法之一,对比 forEach、filter 和 map,在实际使用上好像有些被忽略

语法

arr.reduce ( callback(accumulator,  currentValue [, currentIndex [, sourceArray ] ] ) [, initialValue ] ) 

参数: 

        reduce 方法接收两个参数,第一个参数是回调函数 reducer,第二个参数是 初始值。reducer 函数接收四个参数:

        Accumulator:MDN上解释为累计器,但我觉得不恰当,按我的理解它应该是截至当前元素,之前所有的数组元素被reducer函数处理累计的结果
        CurrentValue:当前被执行的数组元素
        CurrentIndex: 当前被执行的数组元素索引
        SourceArray:原数组,也就是调用reduce方法的数组(可选)

        initialValue 传递给函数的初始值(可选)

        如果传入第二个参数,reduce方法会在这个参数的基础上开始累计执行。

用法:

1、累加求和

数组累加是项目中经常遇到的,比如计算商品总价,使用reduce就可以一行代码搞定,而且不用定义外部变量,reduce是完全无副作用的函数。

//累加
[1,  2,  3,  4,  5,  6].reduce((a, i) => a + i)              // 输出:21

function Accumulation(...vals) {
    return vals.reduce((t, v) => t + v, 0);
}

Accumulation(1, 2, 3, 4, 5)                                    //输出:15

// 累加,默认一个初始值
[1,  2,  3,  4,  5,  6].reduce((a, i) => a + i, 5)          // 输出:26

// 累乘
[1,  2,  3,  4,  5,  6].reduce((a, i) => a * i)                // 输出:720

function Multiplication(...vals) {
    return vals.reduce((t, v) => t * v, 1);
}

Multiplication(1, 2, 3, 4, 5)                                       //输出: 120

2、找出最大数值

在数组每次的迭代中,我们使用Math.max获取最大值并返回,最后我们将得到数组所有项目的最大值。

[1,  2,  3,  4,  5,  6].reduce((a, i) => Math.max(a, i))

当然如果数组每项都是数字我们可以使用...展开运算符和Math.max配合。

Math.max(...[1,  2,  3,  4,  5,  6])

3、处理不规则数组 

通过 map 和 reduce 配合使用,返回每个子数组拼接好的结果。

let data = [
  ["红色","128g", "苹果手机"],
  ["南北","两室一厅","128㎡","洋房住宅"],
  ["小米","白色","智能运动手表","心率血压血氧","来电信息提醒"], 
  ["官方发售","2020年秋季","篮球","球鞋","品牌直邮"]
]
let dataConcat = data.map(item=>item.reduce((a,i)=>`${a} ${i}`))

// 输出结果:
["红色 128g 苹果手机"
"南北 两室一厅 128㎡ 洋房住宅"
"小米 白色 智能运动手表 心率血压血氧 来电信息提醒"
"官方发售 2020年秋季 篮球 球鞋 品牌直邮"]

4、去重

 检查当前迭代项是否存在,如果不存在添加到数组中。

let array = [1, 2, 3, 'a', 'b', 'c', 1, 2, 3, 'a', 'b', 'c'];
array.reduce((noDupes, curVal) => {
  if (noDupes.indexOf(curVal) === -1) { noDupes.push(curVal) }
  return noDupes
}, [])

// 输出:[1, 2, 3, 'a', 'b', 'c']

var arrData = [
    {id: 0, name: "小明"},
    {id: 1, name: "小张"},
    {id: 2, name: "小李"},
    {id: 3, name: "小孙"},
    {id: 1, name: "小周"},
    {id: 2, name: "小陈"},
];
var obj = {};
arrData = arrData.reduce((cur,next) => {
    if(!obj[next.id]){
        obj[next.id] = true
        cur.push(next);
    }
    return cur;
},[]) //设置cur默认类型为数组,并且初始值为空的数组
console.log(arrData);//打印出数组去重后的结果

[ {id: 0, name: '小明'}, 1: {id: 1, name: '小张'}, 2: {id: 2, name: '小李'}, 3: {id: 3, name: '小孙'} ]

5、统计字符串中每个字符出现的次数

每次回调执行的时候,都会往对象中加一个key为字符串,value为出现次数的键值,若已经存储过字符串,那么它的value加1。

const str = 'adefrfdnnfhdueassjfkdiskcddfjds'
const arr = str.split('')
const strObj = arr.reduce((all, current) => {
  if (current in all) {
    all[current]++
  } else {
    all[current] = 1
  }
  return all
}, {})

console.log(strObj)

//输出: {"a":2,"d":7,"e":2,"f":5,"r":1,"n":2,"h":1,"u":1,"s":4,"j":2,"k":2,"i":1,"c":1}

6、按属性分组

 按照指定key将数据进行分组,这里我用国家字段分组,在每次迭代过程中检查当前国家是否存在,如果不存在创建一个数组,将数据插入到数组中。并返回数组。

let obj = [
  {name: '张三', job: '数据分析师', country: '中国'},
  {name: '艾斯', job: '科学家', country: '中国'},
  {name: '雷尔', job: '科学家', country: '美国'},
  {name: '鲍勃', job: '软件工程师', country: '印度'},
]

obj.reduce((group, curP) => {
  let newkey = curP['country']
  if(!group[newkey]){
    group[newkey]=[]
  }
  group[newkey].push(curP)
  return group
}, [])

//输出:[ 中国:{name: '张三', job: '数据分析师', country: '中国'}, {name: '艾斯', job: '科学家', country: '中国'},

美国:{name: '雷尔', job: '科学家', country: '美国'},

印度:{name: '鲍勃', job: '软件工程师', country: '印度'} ]

7、数组扁平化

这里展示的数组只有一级深度,如果数组是多级可以使用递归来进行处理

[[3, 4, 5], [2, 5, 3], [4, 5, 6]].reduce((singleArr, nextArray) => singleArr.concat(nextArray), [])
// 输出:[3, 4, 5, 2, 5, 3, 4, 5, 6]

 当然也可以使用ES6的.flat方法替代

[ [3, 4, 5], 
    [2, 5, 3], 
    [4, 5, 6]
].flat()

//输出:[3, 4, 5, 2, 5, 3, 4, 5, 6]

8、代替reverse,反转字符串

 这也是一种很奇妙的实现方法

[..."hello world"].reduce((a,v) => v+a)       //输出:'dlrow olleh'

或者

[..."hello world"].reverse().join('')            //输出:'dlrow olleh'

或者

function Reverse(arr = []) {
    return arr.reduceRight((t, v) => (t.push(v), t), []);
}

Reverse([1, 2, 3, 4, 5])                       //输出: [5, 4, 3, 2, 1] 

9、权重求和

 const scores = [
    { score: 90, subject: "chinese", weight: 0.5 },
    { score: 95, subject: "math", weight: 0.3 },
    { score: 85, subject: "english", weight: 0.2 }
];
const result = scores.reduce((t, v) => t + v.score * v.weight, 0)         //输出:90.5

10、代替 map 和 filter

const arr = [0, 1, 2, 3];

// 代替map:[0, 2, 4, 6]
const a = arr.map(v => v * 2)      //输出:[0, 2, 4, 6]
const b = arr.reduce((t, v) => [...t, v * 2], [])     //输出:[0, 2, 4, 6]

// 代替filter:[2, 3]
const c = arr.filter(v => v > 1)        //输出:[2, 3]
const d = arr.reduce((t, v) => v > 1 ? [...t, v] : t, [])       //输出:[2, 3]

// 代替map和filter:[4, 6]
const e = arr.map(v => v * 2).filter(v => v > 2)     //输出:[4, 6]
const f = arr.reduce((t, v) => v * 2 > 2 ? [...t, v * 2] : t, [])     //输出:[4, 6]

11、代替some和every

const scores = [
    { score: 45, subject: "chinese" },
    { score: 90, subject: "math" },
    { score: 60, subject: "english" }
];

// 代替some:至少一门合格
const isAtLeastOneQualified = scores.reduce((t, v) => t || v.score >= 60, false)  //输出: true

// 代替every:全部合格
const isAllQualified = scores.reduce((t, v) => t && v.score >= 60, true)       //输出: false

 12、数组分割

function Chunk(arr = [], size = 1) {
    return arr.length ? arr.reduce((t, v) => (t[t.length - 1].length === size ? t.push([v]) : t[t.length - 1].push(v), t), [[]]) : [];
}
const arr = [1, 2, 3, 4, 5];
Chunk(arr, 2)           //输出: [ [1, 2], [3, 4], [5] ]

13、数组过滤 

function Difference(arr = [], oarr = []) {
    return arr.reduce((t, v) => (!oarr.includes(v) && t.push(v), t), []);
}
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [2, 3, 6]
Difference(arr1, arr2)       //输出: [1, 4, 5] 

14、数组填充 

function Fill(arr = [], val = "", start = 0, end = arr.length) {
    if (start < 0 || start >= end || end > arr.length) return arr;
    return [
        ...arr.slice(0, start),
        ...arr.slice(start, end).reduce((t, v) => (t.push(val || v), t), []),
        ...arr.slice(end, arr.length)
    ];
}
const arr = [0, 1, 2, 3, 4, 5, 6];
Fill(arr, "aaa", 2, 5)        //输出: [0, 1, "aaa", "aaa", "aaa", 5, 6] 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值