数组扁平化的多种方案
工作中针对部分嵌套了多层数组的数据,采用数组扁平化能提升代码的可阅读性
同时面试过程中,通常也会被作为一道手写代码题。考察候选人对现有API的熟练度/语法糖和应变能力,通常会叫列出你能实现的所有方案
题目描述
简述:将多维数组转换为一维数组
1.Array.flat
这个方法是ES2019提供的API,可以直接将数组进行扁平化处理
Array.prototype.flat(arr,deep)
- 参数1:
arr
待操作的数组 - 参数2:
deep
展开深度- 默认:1
- 返回:一个新的数组
深度可以指定为 Infinity
,表示展开所有的层级
运行示例
js
console.log([1, [2], [3, [[4]]]].flat(Infinity)); // [1,2,3,4]
console.log([1, [2], [[3]].flat()); // [1,2,[3]]
console.log([1, [2], [[3]].flat(1)); // [1,2,[3]]
console.log([1, [2], [3, [[4]]]].flat(Infinity)); // [1,2,3,4]
console.log([1, [2], [[3]].flat()); // [1,2,[3]]
console.log([1, [2], [[3]].flat(1)); // [1,2,[3]]
当然这个方法并不一定是面试官想要看到的方法。
2. 递归
2.1 常规递归
这个是比较常规的解法,实现方案很多,这里介绍一个简单的:
- 使用
for...of
遍历数组 - 判断每一项的类型,如果是数组则进行递归调用,否则直接加入数组
具体实现如下
js
function myFlat(arr) {
let res = []
// 遍历
for (const a of arr) {
// 判断是否是数组
if(a instanceof Array){
// 是,则递归调用
res = res.concat(myFlat(a))
}else{
// 不是则直接放入
res.push(a)
}
}
return res;
}
console.log(myFlat([1, [2], [3, [[4]]]]));// [1,2,3,4]
function myFlat(arr) {
let res = []
// 遍历
for (const a of arr) {
// 判断是否是数组
if(a instanceof Array){
// 是,则递归调用
res = res.concat(myFlat(a))
}else{
// 不是则直接放入
res.push(a)
}
}
return res;
}
console.log(myFlat([1, [2], [3, [[4]]]]));// [1,2,3,4]
2.2 reduce 递归
调用数组的reduce方法,结合concat方法进行:
- 对每一项进行判断,如果是数组则递归调用
- 否则使用concat进行合并,返回新数组
具体实现如下:
js
let a = [{ a: 1 }, { b: 2 }, 3, 4, 5, [6, [7, 8, [9]]]]
function myFlat(arr) {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? myFlat(cur) : cur)
}, [])
}
console.log(myFlat(a))
// [ { a: 1 }, { b: 2 }, 3, 4, 5, 6, 7, 8, 9 ]
let a = [{ a: 1 }, { b: 2 }, 3, 4, 5, [6, [7, 8, [9]]]]
function myFlat(arr) {
return arr.reduce((pre, cur) => {
return pre.concat(Array.isArray(cur) ? myFlat(cur) : cur)
}, [])
}
console.log(myFlat(a))
// [ { a: 1 }, { b: 2 }, 3, 4, 5, 6, 7, 8, 9 ]
3. replace + JSON.parse + JSON.stringify
这个是代码上比较简介的一个实现,但存在缺陷,如果字符串中的内容本身就包含[
或]
就会直接被处理掉
步骤:
- 执行
JSON.stringify
- 执行
replace
替换掉[
或]
- 再调用
JSON.parse
生成
js
function myFlat(arr) {
arr = JSON.stringify(arr)
arr = JSON.parse('[' + arr.replace(/\[|\]/g, '') + ']')
return arr
}
let a = [{ a: 1 }, { b: 2 }, 3, 4, 5, [6, [7, 8, [9]]]]
console.log(myFlat(a))
// [ { a: 1 }, { b: 2 }, 3, 4, 5, 6, 7, 8, 9 ]
function myFlat(arr) {
arr = JSON.stringify(arr)
arr = JSON.parse('[' + arr.replace(/\[|\]/g, '') + ']')
return arr
}
let a = [{ a: 1 }, { b: 2 }, 3, 4, 5, [6, [7, 8, [9]]]]
console.log(myFlat(a))
// [ { a: 1 }, { b: 2 }, 3, 4, 5, 6, 7, 8, 9 ]
4. 扩展运算符+Array.some迭代
Array.prototype.some
方法判断是否有一项符合条件- 如果有一项是数组则调用扩展运算符进行展开
具体实现如下
js
let a = [{ a: 1 }, { b: 2 }, 3, 4, 5, [6, [7, 8, [9]]]]
function myFlat(arr) {
while (arr.some(Array.isArray)) {
arr = [].concat(...arr)
}
return arr
}
console.log(myFlat(a))
// [ { a: 1 }, { b: 2 }, 3, 4, 5, 6, 7, 8, 9 ]
let a = [{ a: 1 }, { b: 2 }, 3, 4, 5, [6, [7, 8, [9]]]]
function myFlat(arr) {
while (arr.some(Array.isArray)) {
arr = [].concat(...arr)
}
return arr
}
console.log(myFlat(a))
// [ { a: 1 }, { b: 2 }, 3, 4, 5, 6, 7, 8, 9 ]