【问题标题】:How to do a recursive search of this Javascript/JSON tree?如何对这个 Javascript/JSON 树进行递归搜索?
【发布时间】:2014-05-05 06:09:33
【问题描述】:

我正在编写一些 Javascript 代码。我有一个看起来像这样的 JSON 对象(为了便于阅读而修改了间距):

var myNodes = [
    {
        id: 4, 
        children: [
            {
                id: 1, 
                children: [
                ]
            },
            {
                id: 3, 
                children: [
                ]
            }
        ]
    },
    {
        id: 2, 
        children: [
        ]
    },
    {
        id: 6, 
        children: [
            {
                id: 5, 
                children: [
                ]
            }
        ]
    }
]

此数据结构中每个节点的 id 都是唯一的。 但是,除此之外,ID 号之间根本没有固定或已知的关系。 并且每个级别的孩子数量没有限制。

如果我想搜索这棵树并返回 id == 6 的节点。我该怎么做? 我写了以下代码,但是在遇到第一个叶子节点后​​,整个算法返回false,这显然是不对的。我只是想做一个基本的深度优先搜索。但我不想像我在网络上的一些 DFS 实现中看到的那样,向这些数据添加额外的字段并“标记”节点。

myClass.prototype.nodeSearch = function nodeSearch(treeNodes, searchID){
    for (var nodeIdx = 0; nodeIdx <= treeNodes.length-1; nodeIdx++)
    {
        console.log("Comparing treeNodes element with ID==" + treeNodes[nodeIdx].id + " to SearchID==" + searchID);
        if (treeNodes[nodeIdx].id == searchID)
        {    
            console.log("Match!");
            return treeNodes[nodeIdx];
        }
        else
        {
            console.log("No Match! Trying " + treeNodes[nodeIdx].children.length + " Children of Node ID#" + treeNodes[nodeIdx].id);
            return this.nodeSearch(treeNodes[nodeIdx].children, searchID); 
        }
    }
    console.log("Done trying " + treeNodes.length + " children. Returning False");
    return false;
};

【问题讨论】:

    标签: search tree


    【解决方案1】:

    您的算法有问题。你的if 和你的else 都无条件返回,这意味着return 将不可避免地发生在每个循环的第一次迭代中,并且算法只会检查它的每个后代中的第一个(在这种情况下只是节点4和1,仅此而已)。您需要检查递归调用是否返回找到的值,如果是,则仅将其传递给递归树。我认为这应该为您提供一个固定的解决方案:

    myClass.prototype.nodeSearch = function nodeSearch(treeNodes, searchID){
        for (var nodeIdx = 0; nodeIdx <= treeNodes.length-1; nodeIdx++) {
            var currentNode = treeNodes[nodeIdx],
                currentId = currentNode.id,
                currentChildren = currentNode.children;
            console.log("Comparing treeNodes element with ID==" + 
                        currentId + " to SearchID==" + searchID);
            if (currentId == searchID) {    
                console.log("Match!");
                return currentNode;
            }
            else {
                console.log("No Match! Trying " + currentChildren.length + 
                            " Children of Node ID#" + currentId);
                var foundDescendant = this.nodeSearch(currentChildren, searchID); 
                if (foundDescendant) {
                    return foundDescendant;
                }
            }
        }
        console.log("Done trying " + treeNodes.length + " children. Returning False");
        return false;
    };
    

    我还添加了一些变量来帮助使代码有点DRYer 并帮助防止前面提到的一些错误。

    【讨论】:

    • 是的,我相信我在最初的帖子之后找到了根本原因。你能看到我上面的编辑吗?
    【解决方案2】:

    我选择使用json-easy-filter,而不是为类似任务编写自定义解决方案。

    【讨论】:

      【解决方案3】:

      您可以使用 DefiantJS (https://github.com/hbi99/defiant.js)。使用这个 js-lib,您可以使用 XPath 查询搜索 JSON 结构。它就像下面的代码一样简单。 这是 JSFiddle 上的相同代码: http://jsfiddle.net/hbi99/a55au8h5/

      PS:我为此示例代码添加了“名称”属性。

      var myNodes = [
          {
              "id": 4,
              "name": 'name_of_4',
              "children": [
                  {
                      "id": 1,
                      "name": 'name_of_1',
                      "children": []
                  },
                  {
                      "id": 3,
                      "name": 'name_of_3',
                      "children": []
                  }
              ]
          },
          {
              "id": 2,
              "name": 'name_of_2',
              "children": []
          },
          {
              "id": 6,
              "name": 'name_of_6',
              "children": [
                  {
                      "id": 5,
                      "name": 'name_of_5',
                      "children": []
                  }
              ]
          }
      ],
      found = JSON.search(myNodes, '//*[id=6]');
      

      console.log(找到[0].name); // name_of_6

      【讨论】:

        猜你喜欢
        • 2014-04-08
        • 1970-01-01
        • 2011-10-02
        • 2015-05-20
        • 2021-10-20
        • 2017-09-26
        • 2014-01-02
        • 2019-02-03
        相关资源
        最近更新 更多