前言
這幾天都在大量的閱讀,盯著電子書眼睛都快脫窗了,不過也因此複習了一些很核心的概念。在讀到higher-order function的部份時,自然就免不了提到reduce,其中一個練習便是試著用reduce去扁平化巢狀陣列,達到以下的輸出結果。
console.log(flatten([[1, 2, 3], [4, 5], [6]])) // [1,2,3,4,5,6]
當然,用reduce處理並不困難。不過仔細思考並查了一下之後發現,雖然邏輯大致相同,但做法還蠻多樣的,這邊做個簡單的紀錄。
方法一:reduce
第一種方法相對的直觀許多,利用reduce做一個空陣列的加總,並利用concat將每一個item連接。
function flatten(arr) {
return arr.reduce((result,item)=>result.concat(item),[])
}
方法二:concat + apply
方法二其實邏輯上並無二致,一樣是利用空陣列配合concat連接item。
function flatten(arr){
return [].concat.apply([],arr)
}
以上的方法對於扁平範例中的陣列並沒有什麼問題,但萬一是更多層的巢狀陣列呢?(nested array),這邊也提供幾種方法,主要是來自stackoverflow的討論串,有興趣的可以參考一下。
方法三:reduce & recursive
此為方法一的再進階,利用concat連接前先判斷item是否為陣列,若是則利用遞迴先行展開再做連接。語法上雖然較為好懂,但我想效能表現上並不是太優秀,遇到多層或是大陣列應該會有些使用上的疑慮。
function flatten(arr) {
return arr.reduce((result,item)=>Array.isArray(item)?result.concat(flatten(item)):result.concat(item),[])
}
console.log(flatten([[1, 2, 3], [4, 5], [6]]))
//[1, 2, 3, 4, 3, 5, 5, 6]
方法四:ES9 flat
這個方法就有些有意思了,利用ES9推出的flat功能便可以簡單的做到我們所想要的結果,比較需要注意的是使用環境的部份,由於該語法較新,有些瀏覽器或開發環境也許並不支援。(目前不支援IE,但Chrome、Firefox以及Node.js 11.0以上的版本都支援。
flat的用法相當的單純
var newArray = arr.flat([depth]);
depth放你預計的深度,預設為1。所有在該深度以上的巢狀陣列都將被展開,若你無法預測你要處理的陣列究竟有幾層,可以直接用Infinity值~!
[1, 2, [3, 4, [5, 6]]].flat(1) // [1, 2, 3, 4, [5, 6]]
[[1, 2, 3], [4, 5], [6]].flat(Infinity) //[1, 2, 3, 4, 5, 6]
結語
本篇文章介紹了幾種扁平化陣列的做法,當然有許多的函式庫(lodash之類的)也可以協助你輕鬆達成目標,就看個人喜好囉!