Array method 系列之五 —— 數(shù)組扁平化:flatten && flattenDeep && flattenDepth
flatten、flattenDeep、flattenDepth提供了將數(shù)組扁平化的思路。三者唯一的不同在于扁平數(shù)組的層次不同。flatten對數(shù)組進(jìn)行一次扁平操作,flattenDeep扁平數(shù)組所有元素為一維為止。flattenDepth可以制定扁平數(shù)組的深度。
進(jìn)行扁平化的核心代碼是baseFlatten,其實(shí)現(xiàn)思路是遞歸。
源碼如下:
// 判斷數(shù)組元素是否可扁平化
import isFlattenable from './isFlattenable.js'
function baseFlatten(array, depth, predicate, isStrict, result) {
predicate || (predicate = isFlattenable)
result || (result = [])
if (array == null) {
return result
}
for (const value of array) {
if (depth > 0 && predicate(value)) {
if (depth > 1) {
// 遞歸執(zhí)行扁平函數(shù),直至達(dá)到所要的結(jié)果
baseFlatten(value, depth - 1, predicate, isStrict, result)
} else {
result.push(...value)
}
} else if (!isStrict) {
result[result.length] = value
}
}
return result
}
比較flatten、flattenDeep、flattenDepth在執(zhí)行baseFlatten的傳參,即可看到差異。
// flatten
function flatten(array) {
const length = array == null ? 0 : array.length
// depth = 1,執(zhí)行一次扁平操作
return length ? baseFlatten(array, 1) : []
}
// flattenDeep
const INFINITY = 1 / 0
function flattenDeep(array) {
const length = array == null ? 0 : array.length
// 無限次執(zhí)行扁平操作,直至所有元素都為一維。
return length ? baseFlatten(array, INFINITY) : []
}
// flattenDepth
function flattenDepth(array, depth) {
const length = array == null ? 0 : array.length
if (!length) {
return []
}
// 執(zhí)行扁平數(shù)組操作次數(shù)為depth
depth = depth === undefined ? 1 : +depth
return baseFlatten(array, depth)
}
這里有個想法,在flattenDeep中傳參判斷,反倒沒有源碼寫的簡潔。
自己想了下,實(shí)現(xiàn)如下。
for (const value of array) {
if (depth > 0 && predicate(value)) {
if (deepEnd) { // 即flattenDeep執(zhí)行這一步
baseFlatten(value, depth, predicate, isStrict, result, deepEnd)
} else if (depth > 1) {
baseFlatten(value, depth - 1, predicate, isStrict, result, deepEnd)
} else {
result.push(...value)
}
} else if (!isStrict) {
result[result.length] = value
}
}
實(shí)在是沒有源碼簡潔。
所以源碼實(shí)現(xiàn)可以說是非常高明了。