array-flat

数组扁平化

前置知识

浅扁平化

  • 浅扁平化就是只扁平化一层数组

深扁平化

  • 实现无线层级的多维数组扁平化

方法

原始数组

1
var needFlatArr = [1, 2, [3, 4], [[5, 6, 7]], [8, [9, 10], [[11]]]]

浅扁平化实现

  1. concat + apply
1
2
3
4
5
6
7
8
// 1.concat + apply - 浅扁平化
// concat在拼接数组时,若入参中有数组时,则遍历此数组每项(不会递归遍历,仅会遍历一层),并将其依次拼接到尾部
// [].concat(1,[2,3],[4,5],[[6,7]]) 结果[1,2,3,4,5,[6,7]]
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat
function flatConcatApply(arr) {
// 相当于[].concat.(arr[0],arr[1],arr[2],...)
return Array.prototype.concat.apply([], arr)
}
  1. concat + reduce
1
2
3
4
// concat + reduce - 浅扁平化
function flatConcatReduce(arr) {
return arr.reduce((a, b) => a.concat(b), [])
}

深扁平化实现

  1. 递归实现 - 常规实现 - 深扁平化
1
2
3
4
5
6
7
8
9
10
11
function flatRecursion(arr) {
var result = []
for (var i = 0, len = arr.length; i < len; i++) {
if (Object.prototype.toString.call(arr[i]) === '[object Array]') {
result = result.concat(flatRecursion(arr[i]))
} else {
result = result.concat(arr[i])
}
}
return result
}
  1. 递归实现 es6 - 常规实现 - 深扁平化
1
2
3
4
5
6
7
8
9
10
function flatRecursionEs6(arr, result = []) {
for (let item of arr) {
if (Array.isArray(item)) {
flatRecursionEs6(item, result)
} else {
result.push(item)
}
}
return result
}
  1. 递归实现 es6 - 简化 - 深扁平化 - 推荐
1
2
3
4
5
6
7
8
const flatten = arr =>
arr.reduce(
(result, shouldFlatten) =>
result.concat(
Array.isArray(shouldFlatten) ? flatten(shouldFlatten) : shouldFlatten
),
[]
)
  1. 循环实现 - 循环调用浅扁平化函数实现 - lodash 思路 - 深扁平化
1
2
3
4
5
6
7
function flatIterationShallowFlat(arr, deep = 1) {
let result = arr
while (deep--) {
result = flatConcatApply(result)
}
return result
}
  1. toString - 仅支持元素全部为 number 的场景 - 深扁平化
1
2
3
4
5
6
function flatToString(arr) {
return arr
.toString()
.split(',')
.map(item => +item) // 转换为数字类型
}
  1. 字符串过滤 - 将输入数组转换为字符串并删除所有括号([])并将输出解析为数组 - 深扁平化
1
2
const flatStringFilter = arr =>
JSON.parse(`[${JSON.stringify(arr).replace(/\[|]/g, '')}]`)
  1. Generator - 定义生成器函数,并依次调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function* flatG(arr) {
for (let item of arr) {
if (Array.isArray(item)) {
yield* flat(item)
} else {
yield item
}
}
}

function flatGenerator(arr) {
let result = []
for (let val of flatG(arr)) {
result.push(val)
}
return result
}
  1. 原生 flat - 兼容有问题 chrome 高版本不支持 - 深扁平化
1
2
3
4
;[1, 2, [3]]
.flat(1) // [1, 2, 3]
[(1, 2, [3, [4]])].flat(2) // [1, 2, 3, 4]
[(1, 2, [3, [4, [5]]])].flat(Infinity) // [1, 2, 3, 4, 5] 无线层级
  1. 原生 flatMap - 等于 map + flat
1
2
3
// 相当于 [[[2]], [[4]], [[6]], [[8]]].flat()
;[1, 2, 3, 4].flatMap(x => [[x * 2]])
// [[2], [4], [6], [8]]

参考