欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript樹形結(jié)構(gòu)數(shù)組處理之遞歸問題

 更新時(shí)間:2023年06月07日 10:32:50   作者:小熊代碼加  
這篇文章主要介紹了JavaScript樹形結(jié)構(gòu)數(shù)組處理之遞歸問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

JS樹形結(jié)構(gòu)數(shù)組處理之遞歸

經(jīng)典示例

var data = [
?{
? ? ?name: "所有物品",
? ? ?children: [
? ? ? ? ?{
? ? ? ? ? ? ?name: "水果",
? ? ? ? ? ? ?children: [{name: "蘋果", children: [{name: '青蘋果'}, {name: '紅蘋果'}]}]
? ? ? ? ?},
? ? ? ? ?{
? ? ? ? ? ? ?name: '主食',
? ? ? ? ? ? ?children: [
? ? ? ? ? ? ? ? ?{name: "米飯", children: [{name: '北方米飯'}, {name: '南方米飯'}]}
? ? ? ? ? ? ?]
? ? ? ? ?},
? ? ? ? ?{
? ? ? ? ? ? ?name: '生活用品',
? ? ? ? ? ? ?children: [
? ? ? ? ? ? ? ? ?{name: "電腦類", children: [{name: '聯(lián)想電腦'}, {name: '蘋果電腦'}]},
? ? ? ? ? ? ? ? ?{name: "工具類", children: [{name: "鋤頭"}, {name: "錘子"}]},
? ? ? ? ? ? ? ? ?{name: "生活用品", children: [{name: "洗發(fā)水"}, {name: "沐浴露"}]}
? ? ? ? ? ? ?]
? ? ? ? ?}
? ]
}]
//遞歸遍歷實(shí)現(xiàn)
var recursiveFunction = function(){
? ? var str = ''
? ? const getStr = function(list){
? ? ? ? list.forEach(function(row){
? ? ? ? ? ? if(row.children){
? ? ? ? ? ? ? ? getStr(row.children)
? ? ? ? ? ? }else {
? ? ? ? ? ? ? ? str += row.name + ";"
? ? ? ? ? ? }
? ? ? ? })
? ? }
? ? getStr(data)
? ? console.log(str)
}
recursiveFunction()
//輸出:青蘋果;紅蘋果;北方米飯;南方米飯;聯(lián)想電腦;蘋果電腦;鋤頭;錘子;洗發(fā)水;沐浴露;

簡單理解:

let arr = [
?? ?{ name: '小明同學(xué)', children: [ { name: '小明同學(xué)', children: [ { name: '小明同學(xué)' } ] } ] }
]
function fn (arr, newArr = []) {
?? ?arr.forEach(item => {
?? ??? ?typeof item === 'object' && item.name && newArr.push(item.name) ?// 先判斷當(dāng)前項(xiàng)是否是對(duì)象。 當(dāng)前項(xiàng)是否存在你想要的數(shù)據(jù)。都符合,把數(shù)據(jù)push到新數(shù)組里
?? ??? ?item.children && item.children instanceof Array && fn(item.children, newArr) // 當(dāng)前項(xiàng)是否還有子節(jié)點(diǎn),子節(jié)是否是數(shù)組, 如果是繼續(xù)調(diào)用自己。再循環(huán)遍歷一次.
?? ?})
?? ?return newArr
}
fn(arr) // ['小明同學(xué)','小明同學(xué)','小明同學(xué)']
function fn1 (arr, newArr = []) {
?? ?function recursion (arr) {
?? ??? ?arr.forEach(item => {?
?? ??? ??? ?newArr.push(item.name)
?? ??? ??? ?item.children && recursion(item.children)
?? ??? ?})
?? ?}
?? ?recursion(arr)
?? ?return newArr
}
fn1(arr) // ['小明同學(xué)','小明同學(xué)','小明同學(xué)']

遞歸解決多級(jí)數(shù)組

1.我們考慮利用遞歸 就必須等有一個(gè)判斷條件 中斷 遞歸 不然容易出現(xiàn)死循環(huán)

2.我們?cè)谶M(jìn)如函數(shù)遞歸是 要注意第二次調(diào)用自身是 函數(shù)的參數(shù)要是數(shù)據(jù)的子數(shù)據(jù)

實(shí)現(xiàn)邏輯

//js遍歷對(duì)象
function TraversalObject(obj)
{
? ? for (var a in obj) {
? ? ? ? if (typeof (obj[a]) == "object") {
? ? ? ? ? ? TraversalObject(obj[a]); //遞歸遍歷
? ? ? ? }
? ? ? ? else {
? ? ? ? ? ? alert(a + "=" + obj[a]);//值就顯示
? ? ? ? }
? ? }
}
//遍歷對(duì)象中所有Ur的值
function TraversalObject(obj)
{
? ? for (var a in obj) {
? ? ? ? if(a=="Url") ? ?alert(obj[a]);/ /顯示URL的值
? ? ? ? if (typeof (obj[a]) == "object") {
? ? ? ? ? ? TraversalObject(obj[a]); //遞歸遍歷
? ? ? ? }
? ? }
}

這種遍歷方法在對(duì)象不規(guī)則但需要獲取相同屬性時(shí)起到非常好的作用。

復(fù)雜遞歸

遞歸屬性遍歷

一般來說,在JavaScript中考慮復(fù)合類型的深層復(fù)制的時(shí)候,往往就是指對(duì)于Date、Object與Array這三個(gè)復(fù)合類型的處理。

我們能想到的最常用的方法就是先創(chuàng)建一個(gè)空的新對(duì)象,然后遞歸遍歷舊對(duì)象,直到發(fā)現(xiàn)基礎(chǔ)類型的子節(jié)點(diǎn)才賦予到新對(duì)象對(duì)應(yīng)的位置。

不過這種方法會(huì)存在一個(gè)問題,就是JavaScript中存在著神奇的原型機(jī)制,并且這個(gè)原型會(huì)在遍歷的時(shí)候出現(xiàn),然后原型不應(yīng)該被賦予給新對(duì)象。

那么在遍歷的過程中,我們應(yīng)該考慮使用hasOenProperty方法來過濾掉那些繼承自原型鏈上的屬性:

function clone(obj) {
var copy;
? ? // Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
? ? // Handle Date
if (obj instanceof Date) {
? ? ? ? copy = new Date();
? ? ? ? copy.setTime(obj.getTime());
return copy;
? ? }
? ? // Handle Array
if (obj instanceof Array) {
? ? ? ? copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
? ? ? ? ? ? copy[i] = clone(obj[i]);
? ? ? ? }
return copy;
? ? }
? ? // Handle Object
if (obj instanceof Object) {
? ? ? ? copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
? ? ? ? }
return copy;
? ? }
throw new Error("Unable to copy obj! Its type isn't supported.");
}

調(diào)用如下:

// This would be cloneable:
var tree = {
? ? "left" ?: { "left" : null, "right" : null, "data" : 3 },
? ? "right" : null,
? ? "data" ?: 8
};
// This would kind-of work, but you would get 2 copies of the?
// inner node instead of 2 references to the same copy
var directedAcylicGraph = {
? ? "left" ?: { "left" : null, "right" : null, "data" : 3 },
? ? "data" ?: 8
};
directedAcyclicGraph["right"] = directedAcyclicGraph["left"];
// Cloning this would cause a stack overflow due to infinite recursion:
var cylicGraph = {
? ? "left" ?: { "left" : null, "right" : null, "data" : 3 },
? ? "data" ?: 8
};
cylicGraph["right"] = cylicGraph;

不限層級(jí)

//后臺(tái)返回來的數(shù)據(jù)形式
?const data = {
? ? "code":"0",
? ? "data":[
? ? ? ? {
? ? ? ? ? ? "data":{
? ? ? ? ? ? ? ? "name":"xx集團(tuán)香港分公司",
? ? ? ? ? ? ? ? isLeaf:false,
? ? ? ? ? ? ? ? "id":1,
? ? ? ? ? ? ? ? "child":{ ? ??
? ? ? ? ? ? ? ? ? ? "name":"xx集團(tuán)香港分公司第一分部",
? ? ? ? ? ? ? ? ? ? ?isLeaf:false,
? ? ? ? ? ? ? ? ? ? "id":2,
? ? ? ? ? ? ? ? ? ? "child":{
? ? ? ? ? ? ? ? ? ? ? ? "name":"xx集團(tuán)香港分公司第二分部",
? ? ? ? ? ? ? ? ? ? ? ? ?isLeaf:false,
? ? ? ? ? ? ? ? ? ? ? ? "id":3,
? ? ? ? ? ? ? ? ? ? ? ? "child":{
? ? ? ? ? ? ? ? ? ? ? ? ? ? "name":"xx集團(tuán)香港分公司第三分部",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ?isLeaf:false,
? ? ? ? ? ? ? ? ? ? ? ? ? ? "id":4,
? ? ? ? ? ? ? ? ? ? ? ? ? ? "child":{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "name":"xx集團(tuán)香港分公司第第四分部",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?isLeaf:true,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "id":5,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "child":{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//此處省略層數(shù)不定 可能根據(jù)不同的人的權(quán)限層級(jí)樹不一樣 isLeaf為true 代表著在往后已經(jīng)沒有子層級(jí)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ],
? ? "message":"成功"
}
? //因?yàn)殚_發(fā)中我個(gè)人自己開發(fā)和使用的控件是數(shù)組形式的 ?后端不小心弄成都是對(duì)象形式返回來 因?yàn)樯婕暗臉I(yè)務(wù)關(guān)聯(lián)表比較多 不方便改 所以作為前端還得處理,個(gè)人處理如下:
? 預(yù)期想達(dá)到的數(shù)據(jù)結(jié)構(gòu)效果:
?? ?"data":[
? ? {
? ? ? ? "name":"xx集團(tuán)香港分公司",
? ? ? ? isLeaf:false,
? ? ? ? "id":2,
? ? ? ? "child":[ ??
? ? ? ? ? ? {
? ? ? ? ? ? ? ? "name":"xx集團(tuán)香港分公司",
? ? ? ? ? ? ? ? isLeaf:false,
? ? ? ? ? ? ? ? "id":3,
? ? ? ? ? ? ? ? "child":[ ??
? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? "name":"xx集團(tuán)香港分公司",
? ? ? ? ? ? ? ? ? ? ? ? isLeaf:false,
? ? ? ? ? ? ? ? ? ? ? ? "id":4,
? ? ? ? ? ? ? ? ? ? ? ? "child":[ ??
? ? ? ? ? ? ? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "name":"xx集團(tuán)香港分公司",
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? isLeaf:true,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "id":5,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? child:[{
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }]
? ? ? ? ? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? ? ? ]
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ]
? ? ? ? ? ? }
? ? ? ? ]
? ? }
]
? ?//復(fù)雜的對(duì)象轉(zhuǎn)化成為數(shù)組 遞歸實(shí)現(xiàn)
? ? objectToarray(dataObj, arr) {
? ? ? let newObj = {};
? ? ? if (Object.prototype.toString.call(dataObj) === "[object Object]") {
? ? ? ? for (let i in dataObj) {
? ? ? ? ? newObj[i] =
? ? ? ? ? ? i === "child" && !dataObj.isLeaf
? ? ? ? ? ? ? ? this.objectToarray(dataObj[i], [])
? ? ? ? ? ? ? : dataObj[i];
? ? ? ? }
? ? ? ? arr.push(newObj);
? ? ? }
? ? ? return arr;
? ? }
//取到數(shù)據(jù)和將數(shù)據(jù)塞進(jìn)去進(jìn)行處理 靜靜等待結(jié)果
?const dataObj = data.data[0].data;
?const result = objectToarray(dataObj , [])?

JS必會(huì)技巧之遞歸樹結(jié)構(gòu)

列表轉(zhuǎn)化為樹結(jié)構(gòu)(遞歸樹形結(jié)構(gòu))

實(shí)際開發(fā)中,經(jīng)常會(huì)遇到的業(yè)務(wù)需求中,后端傳過來的是數(shù)組中包含許多“形式一樣”的對(duì)象,但實(shí)際這些對(duì)象是由層級(jí)關(guān)系的(樹結(jié)構(gòu))。

因此前端需要經(jīng)過處理,轉(zhuǎn)化為樹結(jié)構(gòu)。

const list = [
    {
        id:1,
        pid:0,
        name:'中國'
    },
    {
        id:2,
        pid:1,
        name:'北京'
    },
    {
        id:3,
        pid:1,
        name:'深圳'
    },
    {
        id:4,
        pid:1,
        name:'武漢'
    },
    {
        id:5,
        pid:1,
        name:'西安'
    },
    {
        id:6,
        pid:2,
        name:'朝陽'
    },
    {
        id:7,
        pid:2,
        name:'海淀'
    }
]
const trancListToTreeData = (data,rootVal)=>{
    const res = [];
    //遍歷查找
    data.forEach((item)=>{
        if(item.pid == rootVal){ //找到了根--找根下面的數(shù)據(jù)
            res.push(item);
            const children = trancListToTreeData(data,item.id) //子節(jié)點(diǎn)
            children.length &&(item.children = children)
        }
    })
    return res;
}
//遍歷樹形的原則--有頭,才知道從哪開始
//要找根
console.log(trancListToTreeData (list,0))

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論