針對這樣一個數組[3,[4,8,[9,1],3],[6,8],[2,10],5,7]想要將其展開,通常都會想到的是利用遞歸。 以下這樣一個方法:es6
function flatten(arr) {
var newArr = [];
arr.map(item => {
if(Array.isArray(item)){
newArr.push(...flatten(item))
} else {
newArr.push(item)
}
})
return newArr
}
複製代碼
可是這樣的方法在數組嵌套很是深的狀況下,函數遞歸調用時,調用層次太深,就會形成棧溢出。何爲棧溢出?數組
棧是一種後進先出的數據結構,堆棧也是採用這種結構管理內存,調用過程當中當最初的結果依賴於後面的計算處理,那麼後面的部分雖而後開始處理,卻先結束。當後續處理太多而且又依賴更後面的處理......(好比遞歸),便會一直壓棧,當空間所有用完,就會形成「堆棧溢出」。 更通俗一點就是向一個水桶裏裝水,等裝滿了以後再加水就溢出了。bash
這時候就應該換一種方法來解決這個問題,調用數組的toString方法或者join方法,將數組變爲字符串而後再用split分割還原爲數組能夠實現。數據結構
function flatten(arr) {
return arr.toString().split(',').map(function(item) {
return Number(item);
})
}
// 或者
function flatten(arr) {
return arr.join(',').split(',').map(function(item) {
return Number(item);
})
}
複製代碼
可是該方法有一個缺點,就是會轉換數組中元素item的類型,須要進行類型轉換。 推薦使用es6的擴展運算符來實現數組扁平化。函數
function flatten(arr) {
let stack = [...arr].reverse()
let newArr = []
while(stack.length){
let o = stack.pop()
if(Array.isArray(o)){
stack.push(...o.reverse())
} else {
newArr.push(o)
}
}
return newArr
}
複製代碼