大廠面試題:手寫數組的Flat方法

前一陣面試大廠的前端崗,讓手擼數組的 Flat方法,很遺憾當時太菜沒有什麼思路,面試後仔細分析了一下,發現這道算法題徹底沒有想象中的那麼難,的確是一套純基礎題,使用數組的reduce結合遞歸能夠很輕鬆的實現,這裏簡單介紹下實現思路,以饗讀者!

前置知識

數組的flat方法:

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方法:

第一次接觸到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)。數組

算法實現

1.使用reduce方法實現提取深度爲1的數組

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]

2.使用數組的解構賦值實現提取深度爲1的數組

function MyFlat(arr){
    return [].concat(...arr)
}

let arr=[1,2,3,4,5,6,[7,8,9]]
console.log(MyFlat(arr))

ps:這個方法有點炫^_^函數

3.使用reduce+遞歸實現多層數組的提取

前面兩個實現的是不傳參的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

待續……

相關文章
相關標籤/搜索