成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

樹轉(zhuǎn)列表的實現(xiàn)思路與代碼

denson / 2962人閱讀

摘要:背景之前寫了一篇列表轉(zhuǎn)樹的文章,有列表轉(zhuǎn)樹的需求自然就會有樹轉(zhuǎn)列表的需求,這里我把樹轉(zhuǎn)列表的思路與代碼再整理一下??偨Y(jié)樹轉(zhuǎn)列表過程中,我這里的深度優(yōu)先采用了遞歸方式,可能會對內(nèi)存占用較多,使用時請自行權(quán)衡。

背景

之前寫了一篇列表轉(zhuǎn)樹的文章,有列表轉(zhuǎn)樹的需求自然就會有樹轉(zhuǎn)列表的需求,這里我把樹轉(zhuǎn)列表的思路與代碼再整理一下。

思路分析

需求是什么?
老規(guī)矩,上圖

先說一下整體思路,就是遍歷樹中的每一個節(jié)點,在遍歷過程中要把節(jié)點的父節(jié)點id記錄下來,并作為該節(jié)點的parentId屬性值(保留層級關系,后續(xù)根據(jù)這個parentId和節(jié)點的id可以轉(zhuǎn)回樹結(jié)構(gòu)),然后把該節(jié)點存入一個列表中。遍歷過程完成,也就實現(xiàn)了把樹結(jié)構(gòu)轉(zhuǎn)換成了列表結(jié)構(gòu)。

樹的遍歷方式有兩種,一種是深度優(yōu)先遍歷,一種是廣度優(yōu)先遍歷,這兩種方式思路如下圖所示:

廣度優(yōu)先:

深度優(yōu)先

思路看這兩個圖應該理得清楚了
我這里深度優(yōu)先遍歷采用了遞歸的方式,然后廣度優(yōu)先遍歷采用了循環(huán)的方式。

執(zhí)行步驟

先說深度優(yōu)先吧:

從第一層開始遍歷,遍歷該層中所有節(jié)點,為每一個遍歷到的節(jié)點添加上parentId屬性,存入結(jié)果列表。

每一個遍歷節(jié)點存入結(jié)果列表后,檢測該節(jié)點是否存在子節(jié)點,如果存在,則將子節(jié)點作為數(shù)據(jù)源重復第一步

當所有的節(jié)點都處理完成后,整個樹結(jié)構(gòu)也就完成了轉(zhuǎn)化

再說說廣度優(yōu)先:

從第一層開始遍歷,遍歷該層中所有節(jié)點,為每一個遍歷到的節(jié)點添加上parentId屬性,存入結(jié)果列表。

每一個遍歷節(jié)點存入結(jié)果列表后,檢測該節(jié)點是否存在子節(jié)點,如果存在,則將子節(jié)點數(shù)據(jù)項push到第一層遍歷的列表中(這里相當于在for循環(huán)的過程中,修改了被遍歷的數(shù)組的內(nèi)容,在循環(huán)過程中把它變長了)

當所有的節(jié)點都處理完成后,整個樹結(jié)構(gòu)也就完成了轉(zhuǎn)化

代碼

深度優(yōu)先

/*
* 深度優(yōu)先遍歷樹
* 一個遞歸方法
* @params tree:要轉(zhuǎn)換的樹結(jié)構(gòu)數(shù)據(jù)
* @params list:保存結(jié)果的列表結(jié)構(gòu)數(shù)據(jù),初始傳[]
* @params parentId:當前遍歷節(jié)點的父級節(jié)點id,初始為null(因為根節(jié)點無parentId)
* */
function toListDF (tree, list, parentId = null) {
    for (let node of tree) {
        list.push({
            id: node.id,
            name: node.name,
            children: [],
            parentId
        })
        if (node.children.length !== 0) {
            toList(node.children, list, node.id)
        }
    }
}

廣度優(yōu)先:

/*
* 廣度優(yōu)先遍歷樹
* 一層循環(huán)
* @params tree:要轉(zhuǎn)換的樹結(jié)構(gòu)數(shù)據(jù)
* @output list:返回轉(zhuǎn)換好的列表結(jié)構(gòu)數(shù)據(jù)
* */
function toListBF (tree) {
    const tempList = tree.slice(0)
    const res = []
    for (let node of tempList) {
        // 向結(jié)果中push每一個節(jié)點的數(shù)據(jù)
        res.push({
            id: node.id,
            name: node.name,
            children: [],
            parentId: node.parentId === undefined ? null : node.parentId
        })
        // 如果該節(jié)點還有子節(jié)點,那么將子節(jié)點追加到待循環(huán)列表的后面
        if (node.children.length !== 0) {
            // 這里注意,push的是children里面的項
            tempList.push(...node.children.map((item) => {
                // 這里給每一項加上parentId
                item.parentId = node.id
                return item
            }))
        }
    }
    return res
}

這里給一個簡單的樹結(jié)構(gòu)數(shù)據(jù)用來測試

const tree = [
    {
        id: 0,
        name: "root",
        children: [
            {
                id: 1,
                name: "child1",
                children: [
                    {
                        id: 4,
                        name: "child1-1",
                        children: []
                    },
                    {
                        id: 5,
                        name: "child1-2",
                        children: []
                    }
                ]
            },
            {
                id: 2,
                name: "child2",
                children: [
                    {
                        id: 6,
                        name: "child2-1",
                        children: [
                            {
                                id: 8,
                                name: "child2-1-1",
                                children: []
                            }
                        ]
                    }
                ]
            },
            {
                id: 3,
                name: "child3",
                children: [
                    {
                        id: 7,
                        name: "child3-1",
                        children: []
                    }
                ]
            }
        ]
    }
]

上面代碼直接扔到瀏覽器中即可運行,可自行看看結(jié)果。

總結(jié)

樹轉(zhuǎn)列表過程中,我這里的深度優(yōu)先采用了遞歸方式,可能會對內(nèi)存占用較多,使用時請自行權(quán)衡。
在廣度優(yōu)先的方式中,只用了一層循環(huán),這里有一個核心的點,就是js在循環(huán)列表過程中,被循環(huán)的列表是可以修改的,比如push一個數(shù)據(jù)項,這樣會讓for循環(huán)多運行一次,這個點理解之后,我這里的廣度優(yōu)先遍歷樹的方法就好理解了。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/95466.html

相關文章

  • angular權(quán)限管理模塊實現(xiàn)思路

    摘要:菜單顯示根據(jù)當前用戶的菜單數(shù)據(jù)顯示相應菜單權(quán)限埋點通過實現(xiàn)只支持控制顯示隱藏操作,報錯等需要自己實現(xiàn) 管理模塊參考界面:http://demo.jeesite.com/js/a/... 菜單管理 列表頁只實現(xiàn)增、刪、改 showImg(https://segmentfault.com/img/bVbjeKu?w=1700&h=512); 新增菜單:去除歸屬模塊字段,其他不變 showI...

    galaxy_robot 評論0 收藏0
  • Vue源碼解析:AST語法樹轉(zhuǎn)render函數(shù)

    摘要:源碼解析這邊解析的是從樹轉(zhuǎn)換成函數(shù)部分的源碼,由于第一次提交的源碼這部分不全,故做了部分更新,代碼全在文件夾中。入口整個語法樹轉(zhuǎn)函數(shù)的起點是文件中的函數(shù)明顯看到,函數(shù)傳入?yún)?shù)為語法樹,內(nèi)部調(diào)用函數(shù)開始解析根節(jié)點容器節(jié)點。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語法樹 AST語法樹轉(zhuǎn)r...

    trilever 評論0 收藏0
  • Vue源碼解析:AST語法樹轉(zhuǎn)render函數(shù)

    摘要:源碼解析這邊解析的是從樹轉(zhuǎn)換成函數(shù)部分的源碼,由于第一次提交的源碼這部分不全,故做了部分更新,代碼全在文件夾中。入口整個語法樹轉(zhuǎn)函數(shù)的起點是文件中的函數(shù)明顯看到,函數(shù)傳入?yún)?shù)為語法樹,內(nèi)部調(diào)用函數(shù)開始解析根節(jié)點容器節(jié)點。 通過對 Vue2.0 源碼閱讀,想寫一寫自己的理解,能力有限故從尤大佬2016.4.11第一次提交開始讀,準備陸續(xù)寫: 模版字符串轉(zhuǎn)AST語法樹 AST語法樹轉(zhuǎn)r...

    Karuru 評論0 收藏0
  • 優(yōu)化項目中樹結(jié)構(gòu)數(shù)據(jù)操作

    摘要:最近在優(yōu)化一段代碼,前端使用的是,頁面中有一個樹形菜單。我想的方法比較直接,一次性查出所有數(shù)據(jù),減少查庫的頻率,畢竟數(shù)據(jù)量也就那么多條。 最近在優(yōu)化一段代碼,前端使用的是Ext3,頁面中有一個樹形菜單。把項目放在本地跑,加載這個樹形菜單的速度似乎還湊合,但是在正式環(huán)境中點開這個頁面,這個樹形菜單加載的就很慢了,很明顯的感覺到卡殼了一下,于是去查看項目代碼,大致思路是這樣的,如下: 通過...

    cppowboy 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<