JS實(shí)現(xiàn)數(shù)組扁平化的方法總結(jié)
嘮一嘮
數(shù)組扁平化相信不少朋喲在一些面試中被問(wèn)到過(guò),這在我們?nèi)粘>幊讨幸彩且粋€(gè)常規(guī)操作,它需要我們將一個(gè)多維數(shù)組轉(zhuǎn)化成一個(gè)一維數(shù)組。當(dāng)然,我相信很多朋友都能回答上這個(gè)問(wèn)題,但如果面試官要我們多回答幾種,可能有些朋友就答不上來(lái)了,所以,借著這篇文章,我們今天就一起來(lái)匯總一下幾種數(shù)組扁平化的方式。
1. 普通遞歸方法
- 相信掘友們首先能想到的實(shí)現(xiàn)數(shù)組扁平化解法是使用遞歸函數(shù)。該方法通過(guò)遍歷數(shù)組中的每個(gè)元素,檢查它是否還是一個(gè)數(shù)組。如果是,則對(duì)子數(shù)組進(jìn)行同樣的扁平化操作,并將結(jié)果合并到最終的一維數(shù)組中。例如:
let arr = [1,2,[3,4,[5,6]]] function flattenArray(arr) { let result = [] for (let i = 0; i < arr.length; i++) { if (Array.isArray(arr[i])) { result = result.concat(flattenArray(arr[i])); } else { result.push(arr[i]) } } return result } console.log(flattenArray(arr)); // [ 1, 2, 3, 4, 5, 6 ]
2. reduce() 方法
- 利用
Array.prototype.reduce()
函數(shù)的累加器特性,遍歷數(shù)組并將子數(shù)組扁平化后的結(jié)果合并到最終的一維數(shù)組中。其實(shí)也是遞歸,不過(guò)不像上面一樣用for循環(huán),和上面代碼差別不大,這里主要是利用了reduce方法,代碼書(shū)寫(xiě)起來(lái)更簡(jiǎn)潔。
let arr = [1,2,[3,4,[5,6,[7,8]]]] function flattenWithReduce(arr) { return arr.reduce((acc, val) => acc.concat(Array.isArray(val) ? flattenWithReduce(val) : [val]), [] ); } console.log(flattenWithReduce(arr)) // [1, 2, 3, 4, 5, 6, 7, 8]
優(yōu)點(diǎn):可讀性強(qiáng),邏輯清晰,無(wú)需額外創(chuàng)建函數(shù)閉包。 缺點(diǎn):對(duì)于非常深的嵌套結(jié)構(gòu),性能可能不如使用flat()方法。
3. Array.prototype.flat()
- ES6引入了
flat()
方法,可以直接對(duì)數(shù)組進(jìn)行扁平化操作,可以指定扁平化的層級(jí)深度。
let arr = [1,2,[3,4,[5,6,[7,8,[9]]]]] function flattenWithFlat(arr) { return arr.flat(Infinity) // Infinity表示完全扁平化所有層級(jí) } console.log(flattenWithFlat(arr)) // [1,2,3,4,5,6,7,8,9]
優(yōu)點(diǎn):簡(jiǎn)潔高效,原生支持,適合現(xiàn)代瀏覽器環(huán)境。 缺點(diǎn):舊版瀏覽器不支持此方法,需要polyfill或其他兼容方案。
4. 擴(kuò)展運(yùn)算符與concat
- 利用擴(kuò)展運(yùn)算符(...)和
concat()
結(jié)合,逐步展開(kāi)嵌套數(shù)組。
let arr = [1,2,[3,[4],[5,6,[7,8,[9]]]]] function flattenWithSpread(arr) { while (arr.some(item => Array.isArray(item))) { arr = [].concat(...arr) } return arr } console.log(flattenWithSpread(arr)); // [1,2,3,4,5,6,7,8,9]
優(yōu)點(diǎn):代碼相對(duì)簡(jiǎn)潔,易于理解。 缺點(diǎn):循環(huán)執(zhí)行次數(shù)取決于數(shù)組嵌套深度,效率相對(duì)較低。
5. 廣度優(yōu)先搜索與隊(duì)列
- 該方法采用廣度優(yōu)先搜索,也就是我們常說(shuō)的BFS策略來(lái)扁平化嵌套數(shù)組。首先創(chuàng)建一個(gè)隊(duì)列并將原數(shù)組作為初始節(jié)點(diǎn)入隊(duì)。然后進(jìn)入循環(huán)階段,只要隊(duì)列不為空,就從隊(duì)列頭部取出一層元素(即當(dāng)前層級(jí)的所有子數(shù)組或值),并檢查每個(gè)元素是否為數(shù)組。如果是數(shù)組,則將其元素逐個(gè)加入隊(duì)列后部;如果不是數(shù)組,則直接將值加入結(jié)果數(shù)組中。循環(huán)直至隊(duì)列為空,此時(shí)結(jié)果數(shù)組中包含了所有已展開(kāi)的一維元素。
let arr = [1,2,[3,[4],[5,6,[7,8,[9]]]]] function flattenWithBFS(arr) { const queue = [arr] // 創(chuàng)建隊(duì)列,初始化為待處理的數(shù)組 const result = [] while (queue.length > 0) { const levelItems = queue.shift() // 取出隊(duì)列首部的一層元素 for (const item of levelItems) { // 遍歷當(dāng)前層級(jí)的每個(gè)元素 if (Array.isArray(item)) { queue.push(item); } else { result.push(item) } } } return result } console.log(flattenWithBFS(arr)) // [1,2,3,4,5,6,7,8,9]
優(yōu)點(diǎn):
- 空間效率較高:通過(guò)使用隊(duì)列結(jié)構(gòu)進(jìn)行層次遍歷,能夠保證在有限的循環(huán)次數(shù)內(nèi)完成對(duì)任何深度嵌套數(shù)組的扁平化。
- 無(wú)需遞歸調(diào)用棧:相比于遞歸方法,這種方法避免了因深層嵌套導(dǎo)致的棧溢出問(wèn)題。
缺點(diǎn):
- 時(shí)間復(fù)雜度:盡管比擴(kuò)展運(yùn)算符結(jié)合concat()的方法有所改進(jìn),但在極端情況下(例如,非常深且寬的樹(shù)形結(jié)構(gòu)),仍需多次迭代才能完全扁平化數(shù)組。
- 代碼相對(duì)復(fù)雜:相較于簡(jiǎn)單的擴(kuò)展運(yùn)算符與concat()結(jié)合的方式,此方法涉及隊(duì)列操作,理解起來(lái)可能需要更多時(shí)間。
6. 深度優(yōu)先搜索與堆棧
- 該方法利用了堆棧數(shù)據(jù)結(jié)構(gòu)進(jìn)行深度優(yōu)先搜索,也就是DFS。首先將待處理的原數(shù)組轉(zhuǎn)換為堆棧,并創(chuàng)建一個(gè)空的結(jié)果數(shù)組用于存儲(chǔ)扁平化后的一維元素。在循環(huán)中,只要堆棧不為空,就從堆棧頂部取出當(dāng)前元素。如果該元素是數(shù)組,則將其所有元素壓入堆棧;如果不是數(shù)組,則直接將其添加到結(jié)果數(shù)組的開(kāi)頭。這個(gè)過(guò)程會(huì)不斷深入到嵌套數(shù)組的最底層,然后再逐層返回,直至堆棧為空。
let arr = [1,2,[3,[4],[5,6,[7,8,[9]]]]] function flattenWithDFS(arr) { const stack = [...arr] // 將原數(shù)組轉(zhuǎn)換為堆棧 const result = [] while (stack.length > 0) { // 當(dāng)堆棧中有待處理元素時(shí) const current = stack.pop() // 取出堆棧頂部的元素 if (Array.isArray(current)) { stack.push(...current) // 將其所有元素壓入堆棧 } else { result.unshift(current) // 否則將非數(shù)組元素添加到結(jié)果數(shù)組的開(kāi)頭 } } return result } console.log(flattenWithDFS(arr)); // [1,2,3,4,5,6,7,8,9]
優(yōu)點(diǎn):
- 遞歸思想簡(jiǎn)化實(shí)現(xiàn):深度優(yōu)先搜索天然適用于解決遞歸問(wèn)題,此方法避免了顯式遞歸調(diào)用,但仍保持了遞歸處理的思想。
- 無(wú)需額外空間復(fù)雜度:相比于廣度優(yōu)先搜索需要隊(duì)列保存每一層級(jí)的數(shù)據(jù),深度優(yōu)先搜索僅需一個(gè)堆棧即可,對(duì)于內(nèi)存資源有限的情況更為友好。
缺點(diǎn):
- 遍歷順序:深度優(yōu)先搜索可能導(dǎo)致元素在扁平化后的一維數(shù)組中的順序與原始嵌套數(shù)組中的層級(jí)順序不同。
- 棧溢出風(fēng)險(xiǎn):當(dāng)面對(duì)極深的嵌套數(shù)組時(shí),由于使用堆棧進(jìn)行遞歸模擬,可能會(huì)遇到JavaScript堆棧大小限制導(dǎo)致的棧溢出錯(cuò)誤。
7. lodash庫(kù)的_.flattenDeep()
- lodash庫(kù)提供了一個(gè)現(xiàn)成的方法
_.flattenDeep()
,可以處理任意深度的嵌套數(shù)組。
import _ from 'lodash' let arr = [1,2,[3,[4],[5,6,[7,8,[9]]]]] const flattenedArr = _.flattenDeep(nestedArr) console.log(flattenedArr)
優(yōu)點(diǎn):第三方庫(kù)封裝,功能強(qiáng)大且經(jīng)過(guò)優(yōu)化,適用于各種復(fù)雜場(chǎng)景。 缺點(diǎn):增加項(xiàng)目依賴,不適合僅需簡(jiǎn)單扁平化且關(guān)注性能與體積的應(yīng)用場(chǎng)景。
以上就是七種常見(jiàn)的數(shù)組扁平化的方式了,掌握了這七種數(shù)組扁平化的方法,這類問(wèn)題相信你回答起來(lái)也會(huì)得心應(yīng)手。今天就聊到這,至于數(shù)組扁平化的應(yīng)用場(chǎng)景本文并未介紹,當(dāng)然這也是一個(gè)非常重要的知識(shí)點(diǎn),不過(guò)本文主要是總結(jié)一些方法,對(duì)于應(yīng)用場(chǎng)景感興趣的掘友們可自行搜索哦。如果還有其他的數(shù)組扁平化方法,歡迎大佬在評(píng)論區(qū)補(bǔ)充哦。
到此這篇關(guān)于JS實(shí)現(xiàn)數(shù)組扁平化的方法總結(jié)的文章就介紹到這了,更多相關(guān)JS數(shù)組扁平化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS+CSS實(shí)現(xiàn)實(shí)用的單擊輸入框彈出選擇框的方法
這篇文章主要介紹了JS+CSS實(shí)現(xiàn)實(shí)用的單擊輸入框彈出選擇框的方法,實(shí)例分析了javascript操作select及button的操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-02-02js從Cookies里面取值的簡(jiǎn)單實(shí)現(xiàn)
遇到一個(gè)Js從Cookies里面取值的需求,Js貌似沒(méi)有現(xiàn)成的方法可以指定Key值獲取Cookie里面對(duì)應(yīng)的值,簡(jiǎn)單實(shí)現(xiàn)如下2014-06-06JavaScript生成隨機(jī)數(shù)的4種自定義函數(shù)分享
這篇文章主要介紹了JavaScript生成隨機(jī)數(shù)的4種自定義函數(shù)分享,本文講解了4種方法并同時(shí)給出4個(gè)代碼片段,需要的朋友可以參考下2015-02-02用JavaScript和jQuery實(shí)現(xiàn)瀑布流
本篇文章主要介紹了用JavaScript和jQuery實(shí)現(xiàn)瀑布流的方法,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03延時(shí)重復(fù)執(zhí)行函數(shù) lLoopRun.js
延時(shí)重復(fù)執(zhí)行函數(shù) lLoopRun.js...2007-05-05ES6基礎(chǔ)之解構(gòu)賦值(destructuring assignment)
這篇文章主要介紹了ES6基礎(chǔ)之解構(gòu)賦值(destructuring assignment),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02微信小程序?qū)崿F(xiàn)搜索關(guān)鍵詞高亮的示例代碼
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)搜索關(guān)鍵詞高亮的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03JavaScript實(shí)現(xiàn)模仿桌面窗口的方法
這篇文章主要介紹了JavaScript實(shí)現(xiàn)模仿桌面窗口的方法,可實(shí)現(xiàn)模仿桌面窗口的打開(kāi)、關(guān)閉、移動(dòng)、縮放及最大化、最小化等功能,需要的朋友可以參考下2015-07-07