前一陣面試大廠的前端崗,讓手擼數組的 Flat方法,很遺憾當時太菜沒有什麼思路,面試後仔細分析了一下,發現這道算法題徹底沒有想象中的那麼難,的確是一套純基礎題,使用數組的reduce結合遞歸能夠很輕鬆的實現,這裏簡單介紹下實現思路,以饗讀者!
Flat()俗稱把數組拍平的方法。
使用flat方法時能夠傳遞一個數字,表明拍平嵌套數組的層數,不傳值的話則爲默認值1。若是咱們傳遞的參數爲Infinity,則會將全部嵌套數組拍平。若是數組中有空元素,則拍平後的數組也不包含空元素javascript
let arr1 = [1, 2, [3, 4]]; arr1.flat(); // [1, 2, 3, 4] let arr2 = [1, 2, [3, 4, [5, 6]]]; arr2.flat(); // [1, 2, 3, 4, [5, 6]] let arr3 = [1, 2, [3, 4, [5, 6]]]; arr3.flat(2); // [1, 2, 3, 4, 5, 6] //使用 Infinity,可展開任意深度的嵌套數組 let arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]; arr4.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] //flat會移除數組中的空項 let arr5 =[1,2,3,,5,[6,7]] console.log(arr5.flat()) //[1, 2, 3, 5, 6, 7]
第一次接觸到Reduce是在學習Hadoop的時候,那時候的理解是對Map後的數據各自執行Reduce處理,而後將處理結果彙總返回。JS中的Reduce與這個概念相似,就是經過一個方法對數組中的元素逐一處理,而後將結果逐一疊加,最後將結果返回出去。好比咱們想要對數組中的元素執行平方後求和,用Reduce就很容易實現,代碼以下:前端
let arr6=[1,2,3]; console.log(arr6.reduce((prev,curr)=>prev+curr*curr,0));
猛一看的確讓人有點費解,大可沒必要。想要搞清楚reduce的使用方式第一步要搞清楚reduce傳遞的參數,爲以下四個:java
參數名 | 含義 |
---|---|
previousValue | 上一個元素(initialValue 或者數組第一項) |
currentValue | 當前元素 |
currentIndex | 當前元素的index |
array | 執行reduce方法的數組對象(通常不用) |
initialValue | 執行reduce方法的初始值 |
在TS中,對Reduce方法定義的類型以下:面試
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T): T; reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue: T): T;
咱們能夠看到,這裏TS定義的reduce數據類型有兩種調用方式,一種爲包含初始值的調用方式,一種是不提供初始值的調用方式,這兩種有什麼區別?這裏咱們不賣關子,直接看例子:算法
let arr6=[2,2,3] console.log(arr6.reduce((prev,curr,index)=>{ console.log(index) return prev+curr*curr })) //輸出爲:1 2 15 let arr6=[2,2,3] console.log(arr6.reduce((prev,curr,index)=>{ console.log(index) return prev+curr*curr },0)) //輸出爲: 0 1 2 17
能夠清楚地看到,提供initialValue後,reduce會從index爲0的元素開始執行回調方法,而不提供initialValue則會將跳過index爲0的元素,直接從index爲1的元素開始執行回調方法(即將index爲0的元素設置爲initialValue)。數組
function MyFlat(arr){ return arr.reduce((prev,curr)=>prev.concat(curr),[]); } let arr=[1,2,3,4,5,6,[7,8,9]]; console.log(MyFlat(arr)); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
function MyFlat(arr){ return [].concat(...arr) } let arr=[1,2,3,4,5,6,[7,8,9]] console.log(MyFlat(arr))
ps:這個方法有點炫^_^函數
前面兩個實現的是不傳參的flat方法,也便是對數組執行層級爲1的提取。若是咱們想指定提取的層級,或者使用Infinity提取任意層數組怎麼作呢?看代碼:oop
function MyFlat(arr,deep=1){ return deep>0 ? arr.reduce((prev,curr)=>prev.concat(Array.isArray(curr)?MyFlat(curr,deep-1):curr),[]):arr.slice() } console.log(MyFlat([1,2,3,[4,5,[6,7,8,[9,10]]]],Infinity)) //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
代碼很短,可是頗有嚼頭。咱們在參數裏增長了一個變量deep表明默認深度,給他一個默認值1。程序會首先判斷deep的深度,若是深度大於零就執行後面的代碼,不然返回數組的副本。
若是深度大於0,咱們會用initialValue也就是空數組去concat數組裏面的元素,在concat的時候咱們會判斷當前元素是否爲數組,若是是數組則遞歸執行MyFlat方法對子元素進行提取。這裏不要忘了,咱們提供了初始值"[]",因此其會從index爲0的元素開始執行回調方法。學習
3.使用生成器函數實現多層數組的提取code
待續……