前言
今天整理一道面试中的经典高频题:数组扁平化。先说一下什么是数组扁平化,简单来说就是把多为数组的元素按顺序放置在一维数组中,使其扁平。比如说[1, 2, 3, 4]
这是一个拥有3个元素的数组,是一个一维数组(不存在数组嵌套)。[[1, 2, 3], [4, 5], [6, 7]]
从整体上看是一个数组,但是其中的元素又是数组,即数组中嵌套数组。可以有二维,三维,n维数组。而数组扁平化就是把多为数组转化成一维数组,比如上文中的二维数组通过扁平化就变成[1, 2, 3, 4, 5, 6, 7]
那么实现数组扁平化有哪些方案呢?
实现数组扁平化的方案
1. 递归
递归的思路非常简单,递归遍历数组的每一项,判断该元素是否为数组,如果为数组时递归进入该数组遍历每一项,如果不为数组则concat
或者使用ES6
拓展运算符...
。
1.1 递归+concat
function flat(arr){
let ret = []
for(let key in arr){
if(Array.isArray(arr[key])){
ret = ret.concat(flat(arr[key]))
}else{
ret.push(arr[key])
}
}
return ret
}
1.2 递归+...
function flat(arr){
let ret = []
for(let key in arr){
if(Array.isArray(arr[key])){
// ret = [...ret, ...flat(arr[key])]
ret = ret.concat(...flat(arr[key]))
}else{
ret.push(arr[key])
}
}
return ret
}
2 while+ES6拓展运算符
es6
的拓展运算符能将二维数组变为一维数组,若arr
中含有数组则使用一次拓展运算符,直到没有为止。
function flat(arr){
while(arr.some(item => {
return Array.isArray(item)
})){
arr = [].concat(...arr)
}
return arr
}
3 使用栈思想
其实就是抛去递归,用一个栈数组存取当前需要遍历的数组,不为数组则放到结果数组,为数组则压栈。
function flat(arr){
let stack = arr
let ret = []
while(stack.length){
let item = stack.pop()
if(Array.isArray(item)){
stack.push(...item)
}else{
ret.unshift(item)
}
}
return ret
}
4 reduce实现
先说一下Array
原型上的reduce
函数。
reduce方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算 为一个值
reduce可以作为一个高阶函数,用于函数的compose
reduce对于空数组是不会执行回调函数的
function flat(arr){
return arr.reduce((total, item) => {
return total.concat(Array.isArray(item) ? flat(item) : item)
}, [])
}
5 flat实现
flat()
函数创建一个新数组,其中所有自数组元素都以递归方式连接到该数组中,直到达到指定的深度为止
let arr = [1, 2, 3, [4, 5, [6, 7], 8, [9, [[10], 11, 12]]]];
console.log(arr.flat(2)) //[1, 2, 3, 4, 5, 6, 7, 8, 9, [9, [[10], 11, 12]]]
let arr = [1, 2, 3, [4, 5, [6, 7], 8, [9, [[10], 11, 12]]]];
console.log(arr.flat(Infinity)) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
6 toString+split实现
调用数组的toString
方法,将数组变为字符串然后再用split
分割还原为数组。split
分割后形成的数组的每一项值为字符串,所以需要用一个map
方法遍历数组将其每一项转换为数值型。
function flatten(arr) {
console.log(arr.toString());// 1,2,3,4,5,6
console.log(arr.toString().split(',')); //[ '1', '2', '3', '4', '5', '6' ]
return arr.toString().split(',').map(function(item) {
return Number(item);
})
}
let ary = [1, [2, [3, [4, 5]]], 6];
console.log(flatten(ary)); // [ 1, 2, 3, 4, 5, 6 ]