Python 無限級分類樹狀結(jié)構(gòu)生成算法的實現(xiàn)
后端研發(fā)的同學(xué)對無限級分類肯定映像深刻,當(dāng)初花了不少時間吧?
無限級分類樹狀結(jié)構(gòu)的應(yīng)用場景很多,例如后端研發(fā)需要把用戶相關(guān)權(quán)限讀取出來并生成樹狀結(jié)構(gòu),前端研發(fā)拿到權(quán)限樹之后可以按照結(jié)構(gòu)展示用戶有權(quán)限訪問的欄目;再例如網(wǎng)頁上的欄目分級:
作者在初次接觸樹狀結(jié)構(gòu)生成需求的時候,也是撓頭,后來找到了一個代碼少且清晰易懂的生成算法:遞歸。
首先,確保數(shù)據(jù)庫中存儲的類別信息如下:
[ {"id": 1, "name": '電器', "parent": 0}, {"id": 2, "name": '水果', "parent": 0}, {"id": 3, "name": '家用電器', "parent": 1}, {"id": 4, "name": '電吹風(fēng)', "parent": 3}, {"id": 5, "name": '電風(fēng)扇', "parent": 3}, {"id": 6, "name": '臺燈', "parent": 3}, {"id": 7, "name": '商用電器', "parent": 1}, {"id": 8, "name": '大型電熱鍋', "parent": 7}, ]
字段 parent 記錄的是此條目的父編號,例如電吹風(fēng)的父編號是 3,即電吹風(fēng)屬于家用電器,而家用電器的父編號是 1,即家用電器屬于電器類產(chǎn)品。電吹風(fēng)條目跟電器條目并無直接的標(biāo)識進(jìn)行關(guān)聯(lián),但需要用樹狀結(jié)構(gòu)來表明 電器 <- 家用電器 <- 電吹風(fēng) 的關(guān)系。
通過 parent 尋找父編號,并建立關(guān)聯(lián)關(guān)系的操作實際上是循環(huán)往復(fù)的,直到找完所有的結(jié)點,這跟遞歸算法非常契合,很輕松便能寫出對應(yīng)的遞歸代碼:
def generate_tree(source, parent): tree = [] for item in source: if item["parent"] == parent: item["child"] = generate_tree(source, item["id"]) tree.append(item) return tree
只需要將數(shù)據(jù)庫中存儲的信息傳遞給 generate_tree 函數(shù)即可。這段遞歸代碼在往復(fù)循環(huán)的過程中通過 parent 來尋找子結(jié)點,找到子結(jié)點后將其添加到樹中。完整代碼如下:
import json def generate_tree(source, parent): tree = [] for item in source: if item["parent"] == parent: item["child"] = generate_tree(source, item["id"]) tree.append(item) return tree if __name__ == '__main__': permission_source = [ {"id": 1, "name": '電器', "parent": 0}, {"id": 2, "name": '水果', "parent": 0}, {"id": 3, "name": '家用電器', "parent": 1}, {"id": 4, "name": '電吹風(fēng)', "parent": 2}, {"id": 5, "name": '電風(fēng)扇', "parent": 3}, {"id": 6, "name": '臺燈', "parent": 3}, {"id": 7, "name": '商用電器', "parent": 1}, {"id": 8, "name": '大型電熱鍋', "parent": 7}, ] permission_tree = generate_tree(permission_source, 0) print(json.dumps(permission_tree, ensure_ascii=False))
你試試運行一下,看看結(jié)構(gòu)是否符合預(yù)期。
使用緩存優(yōu)化算法
遞歸算法中有很多重復(fù)的計算,這些計算不僅占用額外資源,還會降低函數(shù)執(zhí)行效率,因此需要對遞歸進(jìn)行優(yōu)化。這里選用緩存優(yōu)化法提升函數(shù)執(zhí)行效率。
基本思路是每次找到結(jié)點關(guān)系后將此條目的編號添加到一個列表中緩存起來,代表此條目已找到結(jié)點關(guān)系。當(dāng)往復(fù)循環(huán)執(zhí)行函數(shù)時再次遇到此條目可以跳過。代碼改動很簡單,增加一個緩存列表和控制流語句即可:
def generate_tree(source, parent, cache=[]): tree = [] for item in source: if item["id"] in cache: continue if item["parent"] == parent: cache.append(item["id"]) item["child"] = generate_tree(source, item["id"], cache) tree.append(item) return tree
至此,無限級分類樹狀結(jié)構(gòu)生成算法完成。你學(xué)會了嗎?
到此這篇關(guān)于Python 無限級分類樹狀結(jié)構(gòu)生成算法的實現(xiàn)的文章就介紹到這了,更多相關(guān)Python 無限級分類樹狀結(jié)構(gòu)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python中super()的理解以及應(yīng)用場景實例
在python中關(guān)于類的定義可以分為兩種:老式類&新式類,在新式類中有這么一種方法super( ),下面這篇文章主要給大家介紹了關(guān)于Python中super()的理解以及應(yīng)用場景的相關(guān)資料,需要的朋友可以參考下2021-09-09python中from module import * 的一個坑
from module import *把module中的成員全部導(dǎo)到了當(dāng)前的global namespace,訪問起來就比較方便了。當(dāng)然,python style一般不建議這么做,因為可能引起name conflict。2014-07-07Python 爬蟲學(xué)習(xí)筆記之正則表達(dá)式
正則表達(dá)式是用來匹配字符串非常強大的工具,在其他編程語言中同樣有正則表達(dá)式的概念,Python同樣不例外,利用了正則表達(dá)式,我們想要從返回的頁面內(nèi)容提取出我們想要的內(nèi)容就易如反掌了。2016-09-09Python基于socket實現(xiàn)TCP/IP客戶和服務(wù)器通信
本主要介紹了Python socket網(wǎng)絡(luò)編程TCP/IP服務(wù)器與客戶端通信的相關(guān)資料,這里對Scoket 進(jìn)行詳解并創(chuàng)建TCP服務(wù)器及TCP 客戶端實例代碼,需要的朋友可以參考下2021-06-06python中property屬性的介紹及其應(yīng)用詳解
這篇文章主要介紹了python中property屬性的介紹及其應(yīng)用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-08-08