首先什麼是數組展開?
假如如今有這樣一個需求:將後臺的一個多重 List 數據,展開成一個 List 後,並去重後排序;javascript
["a", "b", ["c", "d"], [["d"],"e"], "f"] => ["a", "b", "c", "d", "e"];
複製代碼
數組去重咱們前面在《JS專題之數組去重》已經講過了,那麼前一步的多重數組展開成單層數組,該如何處理呢?java
這就來到咱們所要探討的數組展開了。
根據需求的特色,數組展開須要進行迭代和遞歸。數組
回答文章開頭的問題:閉包
將多重數組轉化成單層數組的過程就是數組展開,也叫做數組扁平化(flatten)app
最簡單的思路:循環中判斷,若是子元素是數組則遞歸。函數
function flatten(origin) {
var result = [];
for(var i = 0; i< origin.length; i++) {
var item = origin[i];
if(Array.isArray(item)) {
result = result.concat(flatten(item))
} else {
result.push(item);
}
}
return result;
}
var arr = ["a", "b", ["c", "d"], [["d"],"e"], "f"];
flatten(arr); // ["a", "b", "c", "d", "d", "e", "f"]
複製代碼
數組的原型對象上有一個方法,toString, 它能把數組的因此元素轉化成用逗號隔開的字符串。post
var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];
arr.toString() // "1,2,3,4,a,b,c,d,d,e,f"
// 因此,利用 split 先把字符串轉化爲單層數組,再進行處理。
const flatten = (origin) => origin.toString().split(','); // ["1", "2", "3", "4", "a", "b", "c", "d", "d", "e", "f"]
複製代碼
因爲 toString 轉化爲字符串的時候,不會區分字符串和數字類型,在進行區分數據類型的時候要注意。ui
上面的方法,咱們用 toString() 將數組轉化爲字符串,那麼咱們也能夠用 split 來作:this
var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];
function flatten(arr) {
return arr.join(',').split(',');
}
console.log(flatten(arr))。 // ["1", "2", "3", "4", "a", "b", "c", "d", "d", "e", "f"]
複製代碼
一樣,這種字符串和數組互轉的過程,不適合多種數據類型同時處理。spa
咱們注意到其實數組扁平化其實就是「迭代 + 拼接(累加) + 遞歸」的過程,數組 reduce 方法既能夠迭代又能夠累加,適合作數組扁平化。
function flatten(origin){
return origin.reduce(function(init, item){
return init.concat(Array.isArray(item) ? flatten(item) : item)
}, [])
}
var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];
console.log(flatten(arr)) // [1, 2, 3, 4, "a", "b", "c", "d", "d", "e", "f"]
複製代碼
some 會遍歷數組的每個元素,判斷是否有元素都知足條件,最後返回布爾值。some 一旦返回真值後,其後的元素就不會繼續監測。
function flatten(origin) {
while (origin.some(item => Array.isArray(item))){
origin = [].concat.apply([], origin);
}
return origin;
}
var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];
console.log(flatten(arr)) // [1, 2, 3, 4, "a", "b", "c", "d", "d", "e", "f"]
複製代碼
ES6 擴展運算符...
能夠將兩重數組轉換爲單層數組:
[].concat(...[1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"]); // [1, 2, 3, Array(1), "a", "b", "c", "d", Array(1), "e", "f"]
// 利用 some 方法,咱們能夠實現多重轉換爲單層:
function flatten(origin) { while(origin.some(item=> Array.isArray(item))) {
origin = [].concat(origin);
} return origin;
}
var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];
console.log(flatten(arr)) // [1, 2, 3, 4, "a", "b", "c", "d", "d", "e", "f"]
複製代碼
JS Array 對象提供了原生的能夠實現扁平化的函數flat:詳細說明見 MDN
var arr = [1, [2, 3, [4]], "a", "b", ["c", "d"], [["d"],"e"], "f"];
// 2 表示深度
arr.flat(2) // [1, 2, 3, 4, "a", "b", "c", "d", "d", "e", "f"];
複製代碼
數組扁平化其實就是利用元素迭代 + 元素拼接(疊加)+ 遞歸調用來對數組進行處理,達到將多層數組轉換爲單層數組的過程。 歡迎關注個人我的公衆號「謝南波」,專一分享原創文章。