📝 个人简介
⭐ 个人主页:我是段段🙋
🍊 博客领域:编程基础、前端💻
🍅 写作风格:干货!干货!都是干货!
🍑 精选专栏:数组
🛸 支持段段:点赞👍、收藏⭐、留言💬
在学习数组扁平化之前,先了解一下reduce()方法~~ QoQ
reduce()方法及高级技巧
reduce()方法接收一个函数作为累加器,数组中的每个值(从左向右)开始缩减,最终计算为一个值。注意:reduce()方法不能对空数组执行回调函数。
1、语法
let arr = []
arr.reduce(callback, [initialValue])
reduce()为数组中的每一个元素依次执行回调函数,其接受两个参数,第一个参数是回调函数,第二个参数是初始值。
callback(previousValue, currentValue, index, arr)
// 其中回调函数接受四个参数:
1、previousValue // reduce()方法提供的初始值(initialValue),或者是上一次调用返回的值
2、currentValue // 数组中的当前元素值
3、index // 当前元素值在数组中的索引
4、arr // 被调用的原数组arr
2、initialValue参数作用
先看不设置initialValue参数的例子:
let arr = [1, 2, 3, 4]
let sum = arr.reduce(function(prev, cur, index, arr){
console.log(prev, cur, index);
return prev + cur
})
console.log(sum, arr);
// 运行结果:
1 2 1
3 3 2
6 4 3
10 [ 1, 2, 3, 4 ]
从上面这个例子可以看出,回调函数的第三个参数:即index,是从1开始的,第一次的prev是数组中的第一个值(1),cur是数组中的第二个值(2);第二次的prev是上次循环返回的二者之和,而cur则变成了数组的第三个值(3),依次类推,但是reduce()函数只循环了三次
当给initialValue参数设置初始值时:
let arr = [1, 2, 3, 4]
let sum = arr.reduce(function(prev, cur, index, arr){
console.log(prev, cur, index);
return prev + cur
}, 0)
console.log(sum, arr);
// 运行结果:
0 1 0
1 2 1
3 3 2
6 4 3
10 [ 1, 2, 3, 4 ]
可以看出运行结果是一样的,不同的是这次prev第一次的值是0,cur的值是数组中的第一个值,索引index也是从0开始的,以此类推,reduce()函数循环的次数和数组的长度相同
结论:如果没有提供initialValue参数,则reduce()函数第一次执行时index的值为1,跳过了第一个索引(0);如果提供了initialValue参数,则从索引为0的地方开始执行reduce()函数
如果初始数组为空,调用reduce()函数会出现什么问题呢?
let arr = []
let sum = arr.reduce(function(prev, cur, index, arr){
console.log(prev, cur, index);
return prev + cur
})
console.log(sum, arr);
//TypeError: Reduce of empty array with no initial value 类型错误:没有初始值的空数组的缩减
但是只要设置了初始值就不会报错:
let arr = []
let sum = arr.reduce(function(prev, cur, index, arr){
console.log(prev, cur, index);
return prev + cur
}, 0)
console.log(sum, arr); // 0 []
3、reduce()简单用法
以往求和求积的方法:for、forEach…
// for:
let arr = [1, 2, 3, 4], sum = 0, pro = 1
for (var i = 0; i < arr.length; i++) {
sum += arr[i]
pro *= arr[i]
}
// forEach:
let arr = [1, 2, 3, 4], sum = 0, pro = 1
arr.forEach( item => {
sum += item
pro *= item
})
而使用reduce()方法可以方便的实现
let arr = [1, 2, 3, 4]
let sum = arr.reduce( function(prev, cur){
return prev + cur
})
console.log(sum) // 10
// 使用Es6中的箭头函数可以简写:
let arr = [1, 2, 3, 4]
let sum = arr.reduce( (prev, cur) => prev + cur)
let pro = arr.reduce( (prev, cur) => prev * cur)
console.log(sum) // 10
console.log(pro) // 24
// 也可以在某一数值基础上进行求和求积:
let arr = [1, 2, 3, 4]
let sum = arr.reduce( function(prev, cur){
return prev + cur
}, 20)
console.log(sum) // 30
// 简洁写法:
let arr = [1, 2, 3, 4]
let sum = arr.reduce( (prev, cur) => prev + cur, 20)
let pro = arr.reduce( (prev, cur) => prev * cur, 2)
console.log(sum) // 30
console.log(pro) // 48
4、reduce()高级用法
(1)统计数组中每一个元素出现的次数
let pos = ['left', 'right', 'top', 'bottom', 'right']
let posNum = pos.reduce( (prev, cur) => {
if(cur in prev){
prev[cur]++
} else{
prev[cur] = 1
}
return prev
}, {})
console.log(posNum) // { left: 1, right: 2, top: 1, bottom: 1 }
(2)数组去重
let arr = [1 ,2 ,3 ,4 ,4 ,1]
let newArr = arr.reduce( (pre, cur) => {
if(!pre.includes(cur)){
return pre.concat(cur)
} else{
return pre
}
}, [])
console.log(newArr) // [ 1, 2, 3, 4 ]
// includes()方法用来判断一个数组是否包含一个指定的值,如果包含则返回true,否则返回false
// concat()方法用于把参数连接到数组中
(3)计算对象中的属性和
var result = [
{
subject: '语文',
score: 80
},
{
subject: '数学',
score: 80
},
{
subject: '英语',
score: 85
}
]
var sum = result.reduce((prev, cur) => cur.score + prev, 0)
console.log(sum) // 245
数组扁平化
数组扁平化就是将一个多维数组转化为一维数组
(1)最基础的方法就是使用原型的isPrototypeOf()方法,用来检测一个对象是否存在于另一个对象的原型链中,如果存在就返回 true,否则就返回 false
let arr = [1, 2, [3, 4, 5, [6, 7, 8, 9]]]
let newArr = []
function fn(arr){
arr.forEach( item => {
Array.prototype.isPrototypeOf(item) ? fn(item) : newArr.push(item)
})
return newArr
}
console.log(fn(arr))
// 运行结果:
[
1, 2, 3, 4, 5,
6, 7, 8, 9
]
(2)也可使用Array.prototype.flat()方法,该方法创建一个新的数组,其中所有子数组元素以递归方式连接到指定的深度
语法: arr.flat(depth)
arr即为需要展平的数组
depth为可选参数,指定嵌套数组结构展平的深度级别,默认为1
let arr = [1, 2, [3, 4, 5, [6, 7, 8, 9]]]
console.log(arr.flat()) // [ 1, 2, 3, 4, 5, [ 6, 7, 8, 9 ] ]
console.log(arr.flat(1)) // [ 1, 2, 3, 4, 5, [ 6, 7, 8, 9 ] ] # 可以看出默认深度为1
console.log(arr.flat(2))
// 结果
[
1, 2, 3, 4, 5,
6, 7, 8, 9
]
console.log(arr.flat(4))
// 当参数深度大于数组嵌套的层数,默认也是将数组展平
[
1, 2, 3, 4, 5,
6, 7, 8, 9
]
(3)reduce()方法将二维数组转化为一维数组
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce( (prev, cur) => {
return prev.concat(cur)
}, [])
console.log(newArr) // [ 0, 1, 2, 3, 4, 5 ]
(4)将多维数组转化为一维数组
let arr = [[0, 1], [2, 3], [4, [5, 6, 7]]]
function fn(arr){
return arr.reduce( (pre, cur) => {
return pre.concat(Array.isArray(cur) ? fn(cur) : cur)
}, [])
}
console.log(fn(arr))
// 结果
[
0, 1, 2, 3,
4, 5, 6, 7
]
(5)Es6扩展运算符
// 二维数组转化为一维数组:
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = []
newArr = newArr.concat(...arr)
console.log(newArr) // [ 0, 1, 2, 3, 4, 5 ]
// 多维数组转化为一维数组:
let arr = [[0, 1], [2, 3], [4, [5, 6, 7]], 8, [9]]
let newArr = []
arr.forEach( item => {
if(Array.isArray(item)){
newArr = newArr.concat(...item)
} else{
newArr.push(item)
}
return newArr
})
console.log(newArr)
// 结果
[
0, 1, 2, 3, 4,
5, 6, 7, 8, 9
]
(6)toString() & split()
调用toString()方法将数组变为字符串,然后使用split()方法进行分割,此时分割好的是字符串数组,需要通过Number()方法将数组中的每项从string类型变为number类型
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = []
newArr = arr.toString().split(',').map(item => Number(item))
console.log(newArr) // [ 0, 1, 2, 3, 4, 5 ]
(7)while()循环&some()
let arr = [1, 2, [4, 5, 6 , [7 ,8]], 9]
while(arr.some(Array.isArray)){
arr = [].concat(...arr)
}
console.log(result)
// 结果
[
1, 2, 4, 5,
6, 7, 8, 9
]
这次的分享就到这里了,觉得学到东西的给博主点点关注~~~