簡體   English   中英

我想獲取所有父節點及其子節點,使用 javascript 中給定數據的子 ID

[英]I want to get all parent nodes along with its child, using a child id for a given data in javascript

這是我的樣本 object,假設如果我給子 ID“services/bsf/diamSetting”,它應該返回一個像這樣的字符串“nf-bsf -> bsfConfig -> services/bsf/diamSetting”

let arr = [{
  "attr": {
    "id": "nf-bsf",
    "name": "BSF",
    "sequence": 1
  },
  "children": [{
    "attr": {
      "id": "bsfGeneralConfig",
      "name": "General Configurations",
      "sequence": 10
    },
    "children": [{
      "attr": {
        "id": "services/bsf/bsfGlobalCfg",
        "name": "General Settings",
        "topic": "bsf.global.cfg",
        "sequence": 10
      }
    }, {
      "attr": {
        "id": "configurations/bsf/sbiErrorCodes",
        "name": "SBI Error Codes",
        "topic": "bsf.sbi.errorcodes",
        "sequence": 20
      }
    }]
  }, {
    "attr": {
      "id": "services/bsf/conLoggingLevel",
      "name": "Logging Level",
      "topic": "consistent.logging.cfg.topics",
      "sequence": 20
    }
  }, {
    "attr": {
      "id": "bsfServices",
      "name": "Service Configurations",
      "sequence": 30
    },
    "children": [{
      "attr": {
        "id": "services/bsf/managementService",
        "name": "Management Service",
        "topic": "bsf.managementservice",
        "sequence": 10
      }
    }]
  }, {
    "attr": {
      "id": "bsfConfig",
      "name": "Diameter Configurations",
      "sequence": 40
    },
    "children": [{
      "attr": {
        "id": "services/bsf/diamSetting",
        "name": "Settings",
        "topic": "common.diamsetting",
        "sequence": 10
      }
    }, {
      "attr": {
        "id": "configurations/bsf/diamPeerNode",
        "name": "Peer Nodes",
        "topic": "common.public.diampeernode",
        "sequence": 20
      }
    }, {
      "attr": {
        "id": "services/bsf/diamRoutingTable",
        "name": "Routing Table",
        "topic": "common.public.diamroutingtable",
        "sequence": 30
      }
    }, {
      "attr": {
        "id": "configurations/bsf/diamLoadShedding",
        "name": "Load Shedding Profiles",
        "topic": "common.public.diamloadshedding",
        "sequence": 40
      }
    }, {
      "attr": {
        "id": "configurations/bsf/diamMessagePriority",
        "name": "Message Priority Profiles",
        "topic": "common.public.diammessagepriority",
        "sequence": 50
      }
    }]
  }, {
    "attr": {
      "id": "bsf-sessionViewer",
      "name": "Session Viewer",
      "sequence": 50
    }
  }, {
    "attr": {
      "id": "administration",
      "name": "Administration",
      "sequence": 60
    },
    "children": [{
      "attr": {
        "id": "bsfBulkExportImport",
        "name": "Export & Import",
        "sequence": 10
      }
    }]
  }]
}];

我嘗試了以下遍歷,我要么得到未定義的路徑,要么得到一些錯誤的路徑。 我什至沒有得到子節點,這將以相反的順序遍歷。

var parent = [];
const findParent = (arr, id) => {
        for (let i=0; i<arr.length; i++) {
          if(arr[i].attr.id == id) {
            return parent;
          } else if (arr[i].children && arr[i].children.length) {
            parent.push(arr[i].attr.id);
            findParent(arr[i].children, id)
          }
        }
      };
let x = findParent(arr, "services/bsf/diamSetting");
console.log(x)

您的parent數組破壞了 function 封裝,造成了多個問題:

  • 當一條路徑被證明是錯誤的時,它永遠不會彈出,從而導致額外的數據。 該數組跟蹤所有訪問過的節點,而不是到目標節點的特定路徑。
  • function 不是冪等的; 多次調用后, parent可能會從之前的遍歷中獲得過時的信息。
  • 如果此全局數據名稱更改,則 function 會中斷。 函數應該能夠承受其 scope 之外的重構。

這是解決這些問題的方法。 我正在使用一個閉包來將結果數組限制在其 function 的本地范圍內, pop以撤消所有未最終導致目標的push ,以及some從搜索中退出並盡快展開調用堆棧找到了目標。

 const tree = [ { "attr": { "id": "nf-bsf", "name": "BSF", "sequence": 1 }, "children": [ { "attr": { "id": "bsfGeneralConfig", "name": "General Configurations", "sequence": 10 }, "children": [ { "attr": { "id": "services/bsf/bsfGlobalCfg", "name": "General Settings", "topic": "bsf.global.cfg", "sequence": 10 } }, { "attr": { "id": "configurations/bsf/sbiErrorCodes", "name": "SBI Error Codes", "topic": "bsf.sbi.errorcodes", "sequence": 20 } } ] }, { "attr": { "id": "services/bsf/conLoggingLevel", "name": "Logging Level", "topic": "consistent.logging.cfg.topics", "sequence": 20 } }, { "attr": { "id": "bsfServices", "name": "Service Configurations", "sequence": 30 }, "children": [ { "attr": { "id": "services/bsf/managementService", "name": "Management Service", "topic": "bsf.managementservice", "sequence": 10 } } ] }, { "attr": { "id": "bsfConfig", "name": "Diameter Configurations", "sequence": 40 }, "children": [ { "attr": { "id": "services/bsf/diamSetting", "name": "Settings", "topic": "common.diamsetting", "sequence": 10 } }, { "attr": { "id": "configurations/bsf/diamPeerNode", "name": "Peer Nodes", "topic": "common.public.diampeernode", "sequence": 20 } }, { "attr": { "id": "services/bsf/diamRoutingTable", "name": "Routing Table", "topic": "common.public.diamroutingtable", "sequence": 30 } }, { "attr": { "id": "configurations/bsf/diamLoadShedding", "name": "Load Shedding Profiles", "topic": "common.public.diamloadshedding", "sequence": 40 } }, { "attr": { "id": "configurations/bsf/diamMessagePriority", "name": "Message Priority Profiles", "topic": "common.public.diammessagepriority", "sequence": 50 } } ] }, { "attr": { "id": "bsf-sessionViewer", "name": "Session Viewer", "sequence": 50 } }, { "attr": { "id": "administration", "name": "Administration", "sequence": 60 }, "children": [ { "attr": { "id": "bsfBulkExportImport", "name": "Export & Import", "sequence": 10 } } ] } ] } ]; const findPath = (children, targetId) => { const path = []; (function search(children) { return children?.some(child => { path.push(child.attr.id); if (child.attr.id === targetId || search(child.children)) { return true; } path.pop(); }); })(children); return path; }; const path = findPath(tree, "services/bsf/diamSetting"); console.log(path.join(" -> "));

使用 function 之外的parent變量將破壞遞歸,因為每個遞歸級別共享一個公共變量,這意味着一個遞歸的結果可能會覆蓋另一個遞歸的先前結果。

您應該改為使parent變量成為findParent本身的私有變量,以便每個遞歸都將創建自己的數組並修改/返回它。

這是一個修改后的代碼,它使用第三個參數hierarchy ,其功能與您的parent相同,但對每個 function 調用都是私有的( 閉包):

 const arr = [ { "attr": { "id": "nf-bsf", "name": "BSF", "sequence": 1 }, "children": [ { "attr": { "id": "bsfGeneralConfig", "name": "General Configurations", "sequence": 10 }, "children": [ { "attr": { "id": "services/bsf/bsfGlobalCfg", "name": "General Settings", "topic": "bsf.global.cfg", "sequence": 10 } }, { "attr": { "id": "configurations/bsf/sbiErrorCodes", "name": "SBI Error Codes", "topic": "bsf.sbi.errorcodes", "sequence": 20 } } ] }, { "attr": { "id": "services/bsf/conLoggingLevel", "name": "Logging Level", "topic": "consistent.logging.cfg.topics", "sequence": 20 } }, { "attr": { "id": "bsfServices", "name": "Service Configurations", "sequence": 30 }, "children": [ { "attr": { "id": "services/bsf/managementService", "name": "Management Service", "topic": "bsf.managementservice", "sequence": 10 } } ] }, { "attr": { "id": "bsfConfig", "name": "Diameter Configurations", "sequence": 40 }, "children": [ { "attr": { "id": "services/bsf/diamSetting", "name": "Settings", "topic": "common.diamsetting", "sequence": 10 } }, { "attr": { "id": "configurations/bsf/diamPeerNode", "name": "Peer Nodes", "topic": "common.public.diampeernode", "sequence": 20 } }, { "attr": { "id": "services/bsf/diamRoutingTable", "name": "Routing Table", "topic": "common.public.diamroutingtable", "sequence": 30 } }, { "attr": { "id": "configurations/bsf/diamLoadShedding", "name": "Load Shedding Profiles", "topic": "common.public.diamloadshedding", "sequence": 40 } }, { "attr": { "id": "configurations/bsf/diamMessagePriority", "name": "Message Priority Profiles", "topic": "common.public.diammessagepriority", "sequence": 50 } } ] }, { "attr": { "id": "bsf-sessionViewer", "name": "Session Viewer", "sequence": 50 } }, { "attr": { "id": "administration", "name": "Administration", "sequence": 60 }, "children": [ { "attr": { "id": "bsfBulkExportImport", "name": "Export & Import", "sequence": 10 } } ] } ] } ]; const findParent = ( arr, id, hierarchy = [] // Use an array here to store parents instead of using an external variable. ) => { for (let i = 0; i < arr.length; i++){ // If id is found, push it to the result array, stop the loop, then return the result. if (arr[i].attr.id === id){ hierarchy.push(arr[i].attr.id); return hierarchy; } // If id is not found, proceed to its children if (arr[i].children && arr[i].children.length){ const childResult = findParent( arr[i].children, id, [...hierarchy, arr[i].attr.id] // Pass the found parents so far to its child recursion. ); // Only stop the loop and return the result if id is found in child. if (childResult){ return childResult; } } // Proceed to the next loop if id is not found in current item AND its offspring children. } // Return null if id is not found in this branch. return null; }; let x = findParent(arr, "services/bsf/diamSetting"); console.log(x && x.join(' -> '));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM