一 問題
1 數(shù)組的扁平化盖喷?
1)就是將一個(gè)n層數(shù)組惩激、即n維數(shù)組(n>=1)轉(zhuǎn)換為只有一層的數(shù)組。
如數(shù)組 arr = [1, [2, [3, 4]]];
經(jīng)過我們 myFlatten 函數(shù)的處理后祟剔、
即調(diào)用 myFlatten(arr) 應(yīng)該得到 [1, 2, 3, 4] 于宙。
【注:以下內(nèi)容均假定 arr = [1, [2, [3, 4]]] 】扛稽。
二 解法一覽
1 解法一覽(思維導(dǎo)圖版)
2 解法一覽(文字版)
1)數(shù)組自帶的方法 —— flat
2)遞歸
3)結(jié)合 reduce函數(shù)
4)(toString && split) 或 (join && split)
5)擴(kuò)展運(yùn)算符 —— …
6)generator
三 具體解法與代碼
1 數(shù)組自帶的方法 —— flat
1)其可以傳入一個(gè)參數(shù)吁峻,表示要 展開的層數(shù) 。
arr.flat();
// 默認(rèn)展開1層在张,即與 arr.flat(1) 一樣用含,均得到 [1, [2, [3, 4]]]
arr.flat(Infinity);
// “無限層”展開,得到 [1, 2, 3, 4]
2 遞歸
1)這是大部分人比較常用的實(shí)現(xiàn)方法帮匾。
function myFlatten(arr) {
// 先定義一個(gè) 保存結(jié)果的 數(shù)組
var res_arr = [];
// 對(duì)原先的數(shù)組進(jìn)行 map遍歷啄骇,
// 根據(jù)當(dāng)前元素是數(shù)組還是“單個(gè)元素”去走向不同的分支
arr.map(item => {
if(Array.isArray(item)){
// 當(dāng)前元素為數(shù)組,繼續(xù)調(diào)用 myFlatten 瘟斜,
// myFlatten返回的是數(shù)組形式缸夹,所以需要使用 concat
res_arr = res_arr.concat(myFlatten(item));
}else{
// 當(dāng)前元素為“單個(gè)元素”,直接 push 塞到結(jié)果數(shù)組
res_arr.push(item);
}
});
// 返回 “當(dāng)前處理的結(jié)果數(shù)組”
return res_arr;
}
3 結(jié)合 reduce函數(shù)
1)遍歷數(shù)組每一項(xiàng)螺句,若值為數(shù)組則繼續(xù)遞歸遍歷虽惭,否則直接 concat 【這個(gè)和方案2的遞歸基本是類似的!】蛇尚。
function myFlatten(arr) {
return arr.reduce((res_arr, cur_item) => {
return res_arr.concat(
// 核心:若為數(shù)組芽唇、繼續(xù)遍歷
Array.isArray(cur_item)
? myFlatten(cur_item)
: cur_item
);
}, []);
}
4 (toString && split) 或 (join && split)
2種方案
// 1)
// 調(diào)用數(shù)組的toString方法,將數(shù)組變?yōu)樽址?// 然后再用split分割還原為數(shù)組
function flatten(arr) {
// 這里的 arr.toString() 會(huì)直接得到 '1,2,3,4' 這樣的字符串
return arr.toString().split(',').map(function(item) {
// return Number(item);
return item;
})
}
// 2)
// 和上面的toString一樣取劫,join也可以將數(shù)組轉(zhuǎn)換為字符串
function flatten(arr) {
// arr.join(',) 得到的也是 '1,2,3,4' 這樣的字符串
return arr.join(',').split(',').map(function(item) {
// return parseInt(item);
return item;
})
}
5 擴(kuò)展運(yùn)算符
1)es6的擴(kuò)展運(yùn)算符能將二維數(shù)組變?yōu)橐痪S匆笤,如:[].concat(…[1, 2, 3, [4, 5]]); // [1, 2, 3, 4, 5]。利用這個(gè)特性谱邪,我們可以做一個(gè)遍歷炮捧,當(dāng) arr 中含有數(shù)組則使用一次擴(kuò)展運(yùn)算符,直到?jīng)]有為止惦银。
function flatten(arr) {
// 核心:只要 arr數(shù)組中含有非一維的 子項(xiàng)寓盗,就繼續(xù) 擴(kuò)展!璧函!
while(arr.some(item=>Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
6 generator
1)如下代碼
function* flatten(array) {
for (const item of array) {
if (Array.isArray(item)) {
yield* flatten(item);
} else {
yield item;
}
}
}
[...flatten(arr)]; // [1, 2, 3, 4]
或者這么調(diào)用【因?yàn)?generator函數(shù)“會(huì)自動(dòng)實(shí)現(xiàn) Iterator傀蚌、遍歷接口”,
使得我們可以使用 for ... of ... 蘸吓,
別寫成了 for ... in ... 善炫。】
let res_arr = [];
for(const item of flatten(arr)) {
res_arr.push(item);
}