简体   繁体   中英

Search in JSON Tree structure preserving Structure

I have a tree structure like below,

                     {
                      uid: 1,
                      children: [
                        {
                          uid: 2
                        },
                        {
                          uid: 3,
                          children: [
                            {
                              uid: 4
                            },
                            {
                              uid: 5,
                              children: [
                                {
                                  uid: 6
                                }
                              ]
                            },
                            {
                              uid: 7
                            }
                          ]
                        }
                      ]
                  }

Now, I want to search tree structure by uid and need output as a tree structure(ie along with its parents, but no siblings)

For example, if I search tree structure for "uid: 4", output result should be something like below,

                    {
                      uid: 1,
                      children: [
                        {
                          uid: 3
                          children: [
                            {
                              uid: 4
                            }
                          ]
                        }
                      ]
                  }

I tried recursion but I failed to fetch matching elements along with parents

I came up with an approach for your problem while implementing search in nested json data in UI. Let me know if this helps or you need something else.

Here is the working code on stackblitz

This algo performs search and recursively updates if the node has to be displayed or not. If a node matches the query, along with it, it's children should also be visible. When traversing back, algo checks if a any of the node's children is visible, the current node will also be visible.

As the execution ends, the nodes will have a displayNode property

  • true indicates it should be visible
  • false indicates it should be hidden
  // Assuming this object won't contain duplicates
  // 'displayNode' property, either true or false, indicating if the node should be visible
  // show the node if 'displayNode' is true
  // else hide

  // main method
  function search(obj, id) {
    if (obj.children && obj.children.length > 0) {
      for (let i = 0; i < obj.children.length; i++) {
        const child = obj.children[i];
        search(child, id);
      }
    }
    if (obj.uid === id) {
      obj['displayNode'] = true;
      // recursively update the children
      // if a node is true, then all it's children should also be visible
      updateObj(obj);
    } else {
      obj['displayNode'] = false;
      // if any children of this node has 'displayNode' true then this should also be visible
      // to complete the path
      if (obj.children && obj.children.length > 0) {
        if (obj.children.find(y => y.displayNode) !== undefined) {
          obj['displayNode'] = true;
        }
      }
    }
  }

  // update children recursivly
  function updateObj(obj) {
    obj['displayNode'] = true;
    if (obj.children && obj.children.length > 0) {
      for (let i = 0; i < obj.children.length; i++) {
        updateObj(obj.children[i]);
      }
    }
  }

  // call method
  search(obj, 4);
  console.log(obj);

Assuming the original JSON tree has no duplicates, and assuming the JSON tree does not always contain sequential uids, and assuming you only want the direct ancestral line, it might be best to use a depth first search ( https://www.tutorialspoint.com/Depth-first-search-traversal-in-Javascript ) on the original JSON tree. You'll also want to keep track of the current direct ancestral line in case the next value matches the one you are searching for. Then you can return the full direct line.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM