JS實現(xiàn)樹形結(jié)構(gòu)與數(shù)組結(jié)構(gòu)相互轉(zhuǎn)換并在樹形結(jié)構(gòu)中查找對象
總是有很多需求是關(guān)于處理樹形結(jié)構(gòu)的,所以不得不總結(jié)幾個常見操作的寫法。
首先假設(shè)有一個樹形結(jié)構(gòu)數(shù)據(jù)如下
var tree=[
{
'id': '1',
'name': '教學(xué)素材管理',
'children':[
{
'id': '101',
'name': '教學(xué)素材',
'children':[
{
'id': '10101',
'name': '修改',
},
{
'id': '10102',
'name': '添加',
}
]
}, {
'id': '102',
'name': '測試試題',
},
{
'id': '103',
'name': '問題任務(wù)',
}
]
}, {
'id': '2',
'name': '基礎(chǔ)數(shù)據(jù)管理',
'children':[
{
'id': '201',
'name': '專業(yè)設(shè)置',
},
{
'id': '202',
'name': '專業(yè)管理',
}
]
}
]1、如何在tree中找到id=10102的對象?
思路一:深度遍歷,從頂點開始,當(dāng)前節(jié)點有子節(jié)點則遍歷當(dāng)前節(jié)點的子節(jié)點(遞歸)。
function deepQuery(tree,id) {
var isGet = false;
var retNode = null;
function deepSearch(tree,id){
for(var i = 0; i<tree.length; i++) {
if(tree[i].children && tree[i].children.length>0) {
deepSearch(tree[i].children,id);
}
if(id === tree[i].id || isGet) {
isGet||(retNode = tree[i]);
isGet = true;
break;
}
}
}
deepSearch(tree,id);
return retNode;
}調(diào)用:
var getNode = deepQuery(tree,10102); console.log(getNode)
思路二:廣度遍歷,遍歷根節(jié)點的所有子節(jié)點,再從第一個子節(jié)點開始依次遍歷。
function breadthQuery(tree, id) {
var stark = [];
stark = stark.concat(tree);
while(stark.length) {
var temp = stark.shift();
if(temp.children) {
stark = stark.concat(temp.children);
}
if(temp.id === id) {
return temp;
}
}
}調(diào)用:
var getNode=breadthQuery(tree,10102); console.log(getNode);
2、如何將樹形結(jié)構(gòu)轉(zhuǎn)換為有父子關(guān)系屬性的數(shù)組結(jié)構(gòu)?
思路一:初始化一個空數(shù)組,從tree的頂端開始遍歷,當(dāng)前節(jié)點有子節(jié)點時,一邊繼續(xù)遍歷子節(jié)點,一邊在當(dāng)前節(jié)點上刪除子節(jié)點,將當(dāng)前節(jié)點push到空數(shù)組。
function flatten1(tree) {
var arr = [];
function spread(tree,pid) {
for (var i=0; i < tree.length; i++ ) {
item = tree[i]
let {id,name}=item;
arr.push({id,name,pid})
if (item.children) {
spread(item.children,item.id)
delete item.children
}
}
}
spread(tree,0)
return arr;
}
var newArr = flatten1(tree);思路二:
function flatten2 (data,pid) {
return data.reduce((arr, {id, name, children = []}) =>
arr.concat([{id, name,pid}], flatten2(children,id)), [])
}
var newArr = flatten2(tree,0);結(jié)果:

3、如何將數(shù)組結(jié)構(gòu)轉(zhuǎn)換為樹形結(jié)構(gòu)?
下面是偶然看到一位大佬很秀的寫法(原文鏈接)
function treeData(data){
let cloneData = JSON.parse(JSON.stringify(data))
return cloneData.filter(parent=>{
let branchArr = cloneData.filter(child => parent['id'] == child['pid']);
branchArr.length>0 ? parent['children'] = branchArr : '';
return parent['pid'] == 0 ;
})
}調(diào)用:
var newTree = treeData(newArr)
用之前測試生成的數(shù)組試一下

結(jié)果如上,完美的生成了最初的樹形結(jié)構(gòu)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
javascript設(shè)計模式之Adapter模式【適配器模式】實現(xiàn)方法示例
這篇文章主要介紹了javascript設(shè)計模式之Adapter模式,結(jié)合實例形式分析了JS適配器模式的原理與具體實現(xiàn)方法,具有一定參考借鑒價值,需要的朋友可以參考下2017-01-01
在b/s開發(fā)中經(jīng)常用到的javaScript技術(shù)
在b/s開發(fā)中經(jīng)常用到的javaScript技術(shù)...2006-08-08
JavaScript創(chuàng)建對象的七種方式(推薦)
JavaScript創(chuàng)建對象的方式有很多,通過Object構(gòu)造函數(shù)或?qū)ο笞置媪康姆绞揭部梢詣?chuàng)建單個對象,顯然這兩種方式會產(chǎn)生大量的重復(fù)代碼,并不適合量產(chǎn)。接下來介紹七種非常經(jīng)典的創(chuàng)建對象的方式,他們也各有優(yōu)缺點2017-06-06
js+HTML5 canvas 實現(xiàn)簡單的加載條(進(jìn)度條)功能示例
這篇文章主要介紹了js+HTML5 canvas 實現(xiàn)簡單的加載條(進(jìn)度條)功能,涉及javascript使用時間函數(shù)與canvas繪圖結(jié)合實現(xiàn)進(jìn)度條的相關(guān)操作技巧,需要的朋友可以參考下2019-07-07
JavaScript的concat方法實例代碼(數(shù)組連接)
這篇文章主要介紹了JavaScript的concat方法實例代碼,包括數(shù)組連與字符連接,需要的朋友可以參考下2023-03-03
JS實現(xiàn)圖片點擊后出現(xiàn)模態(tài)框效果
這篇文章主要介紹了JS實現(xiàn)圖片點擊后出現(xiàn)模態(tài)框效果,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-05-05
postMessage消息通信Promise化的方法實現(xiàn)
postMessage Api 想必大家都不陌生,WebWorker 通信會用到,iframe 窗口之間通信也會用到,那么我們能不能將 postMessage 進(jìn)行一次轉(zhuǎn)化,把他變成類似 Promise 的使用方式,所以本文給大家介紹了postMessage消息通信Promise化的方法實現(xiàn),需要的朋友可以參考下2024-03-03

