【问题标题】:recursively find parents in JSON array backward connect by prev value通过上一个值递归地在 JSON 数组中查找父级反向连接
【发布时间】:2020-06-07 04:10:19
【问题描述】:
[
  {
    "secCode": 2,
    "secName": "GENERAL NURSING CARE SECTION",
    "prevSec": 0,

  },
  {
    "secCode": 1,
    "secName": "CRITICAL CARE NURSING SECTION",
    "prevSec": 0,
    "children": [
      {
        "secCode": 3,
        "secName": "OPERATION THEATRE",
        "prevSec": 1,
        "children": [
          {
            "secCode": 5,
            "secName": "MAIN OPERATION THEATRE",
            "prevSec": 3,
            "estCode": 152,

          },
          {
            "secCode": 6,
            "secName": "DAY CARE DT SERVICE",
            "prevSec": 3,

          }
        ]
      },
      {
        "secCode": 4,
        "secName": "CRITICAL CARE SERVICES",
        "prevSec": 1,
        "children": [
          {
            "secCode": 675,
            "secName": "Test",
            "prevSec": 4,
            "children": [
              {
                "secCode": 676,
                "secName": "Test1",
                "prevSec": 675,

              },
              {
                "secCode": 677,
                "secName": "Test 2",
                "prevSec": 675,

              },
              {
                "secCode": 678,
                "secName": "Test 3",
                "prevSec": 675,

              },
              {
                "secCode": 679,
                "secName": "Test 4",
                "prevSec": 675,

              }
            ]
          },
          {
            "secCode": 7,
            "secName": "ACUTE CARE",
            "prevSec": 4,

          }
        ]
      }
    ]
  }
]

这是tree json树结构。这里每个节点都使用 prevSec 值向后递归地连接到其父节点。 对于 secCode 7,其父树将是 [7, 4, 1] - 通过 secCode = prevSec 连接。 对于 secCode 679,其父级将是 [679, 675, 4, 1] 对于 secCode 2,其父级将是 [2]

我曾尝试过这种部分解决方案

 getParent(arr, childSecCode) {

        if (childSecCode == 0) {
          return;
        } else {
          let val = arr.find(item => {
           childSecCode === item.secCode;
          });
          if (val) {
            //arr.find(item => childSecCode == item.secCode).showChildren = true;
           /*  if(check ==0)
            arr.find(item => childSecCode == item.secCode).className = "selected"; */
            this.getParent(arr, val.prevSec);
          }
        }
      }

这不起作用,因为 find 不检查孩子。

我怎样才能达到预期的效果。

【问题讨论】:

  • 所以,对于给定的secCode,你需要在这个对象中找到路径。对吗?
  • 为什么用 angular 标记?我在问题中看不到任何需要该规范的内容。
  • 为什么 "for 7 它的父树将是 [7, 4, 3, 1]" 当 4 的父节点是 1 而不是 3 时?在那里获得3的逻辑是什么?与其他示例相同...
  • 为什么要向getParent 传递两个 参数?为什么不只是根是您需要其父项的子树?最好知道在哪种情况下需要此方法。我相信可以设计得更好。最好看看发生这种情况的类,以及整个数据结构存储在哪里,这样我们就可以从根目录访问它。
  • @trincot 在结果 3 中被错误地添加。我已将其删除并更新了问题。

标签: javascript angular angular5


【解决方案1】:

如果你想避免在需要时搜索整个树,最好先预处理你的树,这样你就可以在恒定时间内直接找到任何节点(对象),给定它的secCode

您可以为secCode 和节点之间的连接创建一个Map

// Creates a map which is keyed by secCode, and for a secCode provides 
//   the corresponding node from the tree
function createMap(tree) {
    let map = new Map;
    
    function recur(node) {
        map.set(node.secCode, node);
        if (node.children) node.children.forEach(recur);
    }
    
    tree.forEach(recur);
    return map;
}

// Uses the map to walk up the tree
function getParents(secCode, map) {
    let parents = [];
    while (secCode) {
        parents.push(secCode);
        let node = map.get(secCode);
        secCode = node.prevSec;
    }
    return parents;
}

// The tree from the question:
let tree = [{"secCode": 2,"secName": "GENERAL NURSING CARE SECTION","prevSec": 0,},{"secCode": 1,"secName": "CRITICAL CARE NURSING SECTION","prevSec": 0,"children": [{"secCode": 3,"secName": "OPERATION THEATRE","prevSec": 1,"children": [{"secCode": 5,"secName": "MAIN OPERATION THEATRE","prevSec": 3,"estCode": 152,},{"secCode": 6,"secName": "DAY CARE DT SERVICE","prevSec": 3,}]},{"secCode": 4,"secName": "CRITICAL CARE SERVICES","prevSec": 1,"children": [{"secCode": 675,"secName": "Test","prevSec": 4,"children": [{"secCode": 676,"secName": "Test1","prevSec": 675,},{"secCode": 677,"secName": "Test 2","prevSec": 675,},{"secCode": 678,"secName": "Test 3","prevSec": 675,},{"secCode": 679,"secName": "Test 4","prevSec": 675,}]},{"secCode": 7,"secName": "ACUTE CARE","prevSec": 4,}]}]}];
// Preprocessing
let map = createMap(tree);
// Example calls:
console.log(getParents(7, map));
console.log(getParents(679, map));

请注意,您的示例中的树没有 4 作为您的示例所暗示的 3 的子级 - 4 是 1 的子级。

如果你有一个类,你当然可以在其构造函数中创建该映射并将其分配给一个属性:

class Tree {
    constructor(data) {
        this.map = new Map;

        const recur = (node) => {
            this.map.set(node.secCode, node);
            if (node.children) node.children.forEach(recur);
        }

        data.forEach(recur);
    }
    getParents(secCode) {
        let parents = [];
        while (secCode) {
            parents.push(secCode);
            secCode = this.map.get(secCode).prevSec;
        }
        return parents;
    }
}

// The tree from the question:
let data = [{"secCode": 2,"secName": "GENERAL NURSING CARE SECTION","prevSec": 0,},{"secCode": 1,"secName": "CRITICAL CARE NURSING SECTION","prevSec": 0,"children": [{"secCode": 3,"secName": "OPERATION THEATRE","prevSec": 1,"children": [{"secCode": 5,"secName": "MAIN OPERATION THEATRE","prevSec": 3,"estCode": 152,},{"secCode": 6,"secName": "DAY CARE DT SERVICE","prevSec": 3,}]},{"secCode": 4,"secName": "CRITICAL CARE SERVICES","prevSec": 1,"children": [{"secCode": 675,"secName": "Test","prevSec": 4,"children": [{"secCode": 676,"secName": "Test1","prevSec": 675,},{"secCode": 677,"secName": "Test 2","prevSec": 675,},{"secCode": 678,"secName": "Test 3","prevSec": 675,},{"secCode": 679,"secName": "Test 4","prevSec": 675,}]},{"secCode": 7,"secName": "ACUTE CARE","prevSec": 4,}]}]}];
// Preprocessing
let tree = new Tree(data);
// Example calls:
console.log(tree.getParents(7));
console.log(tree.getParents(679));

【讨论】:

  • 让 tree = new Tree(data); // 树未定义错误
  • 不确定您的意思? sn-ps 不会产生这个错误?
【解决方案2】:

你需要像这样递归遍历你的数据结构。

getParent(arr, childSecCode){
  for(let i=0; i<arr.length;i++) {
    const item = arr[i];
    if(item.secCode === childSecCode)
      return item.prevSec; // found item
    if(item.children) {
      const prevSec = getParent(item.children, childSecCode);
      if(prevSec) return prevSec;
    }
  }
}

此方法使用深度优先算法。

【讨论】:

    猜你喜欢
    • 2017-03-23
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 2012-10-18
    • 2013-09-15
    • 1970-01-01
    • 1970-01-01
    • 2020-09-07
    相关资源
    最近更新 更多