JavaScript前端面試扁平數(shù)據(jù)轉(zhuǎn)tree與tree數(shù)據(jù)扁平化
一、寫在前面
有時我們拿到的數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)可能不是理想的,那么此時就要求前端程序員,具有改造數(shù)據(jù)的能力。例如拿到扁平的數(shù)據(jù), 但我們要應(yīng)用在 tree 樹形組件或 Cascader 級聯(lián)選擇器組件中,這樣的組件要求數(shù)據(jù)結(jié)構(gòu)是非扁平的的具有層級遞進(jìn)關(guān)系的 tree 結(jié)構(gòu)。
總之就是說,提供數(shù)據(jù)的接口給到的數(shù)據(jù),未必符合要求,而當(dāng)我們又無法令他人為為我們改變時,需求和要求就來到了前端程序員這里, 所以得具備這樣的數(shù)據(jù)處理能力。
下面是將舉兩個數(shù)據(jù)改造的例子:
- 一是扁平化,具有層級遞進(jìn)關(guān)系的 tree 數(shù)據(jù),轉(zhuǎn)換為扁平結(jié)構(gòu)的的 flat 數(shù)據(jù)
- 二是反扁平化,扁平結(jié)構(gòu)的 flat 數(shù)據(jù),轉(zhuǎn)換為具有層級遞進(jìn)關(guān)系的 tree 數(shù)據(jù)
二、正文部分
2.1 扁平數(shù)據(jù)轉(zhuǎn)為 tree 數(shù)據(jù)
扁平化函數(shù)
/** * 扁平化:將具有層級遞進(jìn)關(guān)系結(jié)構(gòu)的 tree 數(shù)據(jù)扁平化 * * @param treeList 有層級遞進(jìn)關(guān)系結(jié)構(gòu)的 tree 數(shù)據(jù) * @param flatList 用于接收扁平化結(jié)果的變量 * @returns {*} 返回扁平化結(jié)果 */ function treeToFlat (treeList, flatList) { // flatList.length > 9999 是考慮底線保護(hù)原則,出于極限保護(hù)的目的設(shè)置的,可不設(shè)或按需設(shè)置。 if (flatList.length > 9999) { return } treeList.map(e => { flatList.push(e) // 遞歸:有條件的自己調(diào)用自己,條件是 e.children.length 為真 if (e.children && e.children.length) { treeToFlat(e.children, flatList) } }) // console.log('扁平化后:', flatList) return flatList }
2.2 tree 數(shù)據(jù)轉(zhuǎn)為扁平數(shù)據(jù)
反扁平化函數(shù)
/** * 反扁平化:將扁平結(jié)構(gòu)的 flat 數(shù)據(jù)轉(zhuǎn)換為具有層級遞進(jìn)關(guān)系結(jié)構(gòu)的 tree 數(shù)據(jù) * * @param flatList 扁平結(jié)構(gòu)的數(shù)據(jù) * @param treeList 用于接收反扁平化結(jié)果的變量 * @returns {*} 返回反扁平化結(jié)果 */ function flatToTree (flatList, treeList) { flatList.map(e => { // 以 e.pid===null,作為判斷是不是根節(jié)點的依據(jù),或者直接寫死根節(jié)點(如果確定的話), // 具體以什么作為判斷根節(jié)點的依據(jù),得看數(shù)據(jù)的設(shè)計規(guī)則,通常是判斷層級或是否代表根節(jié)點的標(biāo)記 if (e.pid === null) { // 避免出現(xiàn)重復(fù)數(shù)據(jù) const index = treeList.findIndex(sub => sub.id === e.id) if (index === -1) { treeList.push(e) } } flatList.map(e2 => { if (e2.pid === e.id) { // 避免出現(xiàn)重復(fù)數(shù)據(jù) const index = e.children.findIndex(sub => sub.id === e2.id) if (index === -1) { e.children.push(e2) } } }) })
2.3 完整測試 demo
demo 測試結(jié)果截圖如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>扁平數(shù)據(jù)轉(zhuǎn)tree與tree數(shù)據(jù)扁平化 Demo</title> </head> <body> <h1>扁平數(shù)據(jù)轉(zhuǎn)tree與tree數(shù)據(jù)扁平化</h1> <script> window.onload = function () { test() } function test () { let flatList = [], treeList = [ { id: 1, pid: null, label: '第一層', value: '1', children: [ { id: 2, pid: 1, label: '第二層1', value: '2.1', children: [] }, { id: 3, pid: 1, label: '第二層2', value: '2.2', children: [] }, { id: 4, pid: 1, label: '第二層3', value: '2.3', children: [ { id: 5, pid: 4, label: '第三層1', value: '3.1', children: [] }, { id: 6, pid: 4, label: '第三層2', value: '3.2', children: [] }, ] }, ] } ] console.log('原始 tree 數(shù)據(jù):', JSON.parse(JSON.stringify(treeList))) // 扁平化 console.log('tree =>flat,扁平化后:', treeToFlat(JSON.parse(JSON.stringify(treeList)), flatList)) // 反扁平化,SON.parse(JSON.stringify()) 為了實現(xiàn)深拷貝 console.log('flat =>tree,反扁平化后:', flatToTree(JSON.parse(JSON.stringify(flatList)), treeList)) } /** * 扁平化:將具有層級遞進(jìn)關(guān)系結(jié)構(gòu)的 tree 數(shù)據(jù)扁平化 * * @param treeList 有層級遞進(jìn)關(guān)系結(jié)構(gòu)的 tree 數(shù)據(jù) * @param flatList 用于接收扁平化結(jié)果的變量 * @returns {*} 返回扁平化結(jié)果 */ function treeToFlat (treeList, flatList) { // flatList.length > 9999 是考慮底線保護(hù)原則,出于極限保護(hù)的目的設(shè)置的,可不設(shè)或按需設(shè)置。 if (flatList.length > 9999) { return } treeList.map(e => { flatList.push(e) // 遞歸:有條件的自己調(diào)用自己,條件是 e.children.length 為真 if (e.children && e.children.length) { treeToFlat(e.children, flatList) } }) // console.log('扁平化后:', flatList) return flatList } /** * 反扁平化:將扁平結(jié)構(gòu)的 flat 數(shù)據(jù)轉(zhuǎn)換為具有層級遞進(jìn)關(guān)系結(jié)構(gòu)的 tree 數(shù)據(jù) * * @param flatList 扁平結(jié)構(gòu)的數(shù)據(jù) * @param treeList 用于接收反扁平化結(jié)果的變量 * @returns {*} 返回反扁平化結(jié)果 */ function flatToTree (flatList, treeList) { flatList.map(e => { // 以 e.pid===null,作為判斷是不是根節(jié)點的依據(jù),或者直接寫死根節(jié)點(如果確定的話), // 具體以什么作為判斷根節(jié)點的依據(jù),得看數(shù)據(jù)的設(shè)計規(guī)則,通常是判斷層級或是否代表根節(jié)點的標(biāo)記 if (e.pid === null) { // 避免出現(xiàn)重復(fù)數(shù)據(jù) const index = treeList.findIndex(sub => sub.id === e.id) if (index === -1) { treeList.push(e) } } flatList.map(e2 => { if (e2.pid === e.id) { // 避免出現(xiàn)重復(fù)數(shù)據(jù) const index = e.children.findIndex(sub => sub.id === e2.id) if (index === -1) { e.children.push(e2) } } }) }) // console.log('反扁平化后:', treeList) return treeList } </script> </body> </html>
三、寫在后面
這兩個扁平化與反扁平化寫法,感覺還有值得優(yōu)化的方法,但暫時想不到。
此外,遞歸的應(yīng)用也是值得注意的地方。
我理解的遞歸:有條件的自己調(diào)用自己
以上就是JavaScript前端面試扁平數(shù)據(jù)轉(zhuǎn)tree與tree數(shù)據(jù)扁平化的詳細(xì)內(nèi)容,更多關(guān)于扁平數(shù)據(jù)轉(zhuǎn)tree數(shù)據(jù)扁平化的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
js獲取對象、數(shù)組的實際長度,元素實際個數(shù)的實現(xiàn)代碼
下面小編就為大家?guī)硪黄猨s獲取對象、數(shù)組的實際長度,元素實際個數(shù)的實現(xiàn)代碼。小編覺得挺不錯的,現(xiàn)在就分享 給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-06-06JS PHP字符串截取函數(shù)實現(xiàn)原理解析
這篇文章主要介紹了JS PHP字符串截取函數(shù)實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-08-08BootStrap table實現(xiàn)表格行拖拽效果
這篇文章主要為大家詳細(xì)介紹了BootStrap table實現(xiàn)表格行拖拽效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-12-12JavaScript選取(picking)和反選(rejecting)對象的屬性方法
這篇文章主要介紹了JavaScript選取(picking)和反選(rejecting)對象的屬性方法的相關(guān)資料,需要的朋友可以參考下2017-08-08