一、生活場景:什么叫"數(shù)組不扁平"?
想象你收拾衣柜:
- 千層餅數(shù)組:
[襪子, [褲子, [上衣, 腰帶]], 鞋子]
(找雙襪子要翻三層) - 扁平數(shù)組:
[襪子, 褲子,上衣,腰帶,鞋子]
(一目了然)
需求:把嵌套數(shù)組變成一維數(shù)組,就是扁平化!
二、青銅選手:flat()
方法(ES10真香)
const messyCloset = ['襪子', ['褲子', ['上衣', '腰帶']], '鞋子'];
const level1 = messyCloset.flat();
const allFlat = messyCloset.flat(Infinity);
我的翻車史:
曾經(jīng)以為flat(2)
和flat(Infinity)
效果一樣,直到遇到五層嵌套數(shù)組...
三、白銀選手:reduce
+遞歸(經(jīng)典永流傳)
function flatten(arr) {
return arr.reduce((result, item) => {
return result.concat(
Array.isArray(item) ? flatten(item) : item
);
}, []);
}
const myCloset = ['??', ['??', ['??']], '??'];
console.log(flatten(myCloset));
適用場景:
- 需要兼容老瀏覽器時
- 面試官盯著你手寫實現(xiàn)時 ??
四、黃金選手:toString
妙用(數(shù)字數(shù)組專屬)
const numLayers = [1, [2, [3, [4]]]];
const strFlat = numLayers.toString().split(',');
const numFlat = strFlat.map(Number);
致命缺陷:
- 會把
[1, 'a']
變成['1', 'a']
- 遇到
null, undefined
直接轉(zhuǎn)字符串
五、鉑金選手:生成器函數(shù)(優(yōu)雅處理海量數(shù)據(jù))
function* flattenGen(arr) {
for (const item of arr) {
Array.isArray(item) ? yield* flattenGen(item) : yield item;
}
}
const hugeArray = [1, [2, [3, [4, ...[1000000個項]]]];
const flattened = [...flattenGen(hugeArray)];
性能優(yōu)勢:
處理超大規(guī)模數(shù)組時,不會一次性占用大量內(nèi)存
六、鉆石選手:棧結(jié)構(gòu)迭代(避免遞歸爆棧)
function flattenStack(arr) {
const stack = [...arr];
const result = [];
while (stack.length) {
const next = stack.pop();
Array.isArray(next) ? stack.push(...next) : result.push(next);
}
return result.reverse();
}
const deepArray = [1, [2, [3, [4]]];
console.log(flattenStack(deepArray));
適用場景:
- 嵌套層級極深時(遞歸可能棧溢出)
- 需要控制遍歷順序時
七、王者選手:Array.prototype.flatMap
(ES2019)
const data = [1, [2], 3];
const processed = data.flatMap(item =>
Array.isArray(item) ? item : [item * 2]
);
神技巧:
用flatMap
實現(xiàn)過濾+展開二合一:
const mixed = [1, 2, , , 5];
const compact = mixed.flatMap(x => x || []);
八、終極選擇指南
場景 | 推薦方案 | 原因 |
---|
現(xiàn)代瀏覽器環(huán)境 | flat(Infinity) | 原生API性能最佳 |
需要兼容IE | reduce +遞歸 | 兼容性好 |
純數(shù)字數(shù)組 | toString +split | 取巧但高效 |
超大數(shù)據(jù)量 | 生成器函數(shù) | 內(nèi)存友好 |
需要控制遍歷順序 | 棧結(jié)構(gòu)迭代 | 避免遞歸爆棧 |
需要邊處理邊展開 | flatMap | 代碼最簡潔 |
九、真實案例:樹形菜單扁平化
const menuTree = [
{
name: '文件',
children: [
{ name: '新建' },
{ name: '打開', children: [{ name: '從云端' }] }
]
}
];
function getAllNames(items) {
return items.flatMap(item => [
item.name,
...(item.children ? getAllNames(item.children) : [])
]);
}
console.log(getAllNames(menuTree));
轉(zhuǎn)自https://juejin.cn/post/7511969803557584937
該文章在 2025/6/5 11:03:14 編輯過