0

What is the cleanest way to find object and return that based on id , If I don't know how many nested object there will be in my object ?

Let's say I have the following structure :

  myObj = {
              "id": "5e6b8961ba08180001a10bb6",
              "children": [
                {
                  "id": "5e6b8961ba08180001a10bb7",
                  "refrenceId": "SEC-02986",
                  "children": [
                    {
                      "id": "5e58d7bc1bbc71000118c0dc"
                    },
                    {
                      "id": "5e58d7bc1bbc71000118c0dd",
                      "refrenceId": "SKU-00343"
                     },
                    {
                      "id": "5e590d571bbc71000118c102",
                      "refrenceId": "SKU-05290"
                    },
                    {
                      "id": "5e590df71bbc71000118c109",
                      "children": [
                        {
                          "id": "5e590df71bbc71000118c10a"
                        },
                        {
                          "id": "5e590df71bbc71000118c10b",
                          "refrenceId": "SKU-00444"
                    },
                    {
                      "id": "5e5cb9428ae591000177c0f6"
                    }
                  ]
                },
                {
                  "id": "5e81899f0bab450001dcfc1d",
                  "refrenceId": "SEC-03260"
                },
                {
                  "id": "5e81c4b51503860001f97f6c",
                  "refrenceId": "SEC-03267",
                  "children": [
                    {
                      "id": "5e8ad5175d374200014edb3a",
                      "refrenceId": "SEC-03409",
                      "children": [
                        {
                          "id": "5e8f28882d94c1000156bebe"
                        }
                      ]
                    },
                    {
                      "id": "5e8ad5175d374200014edb3c",
                       "refrenceId": "SEC-03410"
                    },
                    {
                      "id": "5e8f29082d94c1000156bec6",
                      "refrenceId": "SEC-03495"
                    }
                  ]
                }
              ]
            }

Suppose, I want to find the one with id "5e590df71bbc71000118c10b", and return that object from nested object.

I have tried using following code:

   function nodeHasChildren(children, id) {

    for (const child of children) {

      if (child.id === id) {

        if (Array.isArray(child.children) && child.children.length > 0) {
          return child;
        }
      }
      else {
          const result = nodeHasChildren(child.children, id);

        if (result !== undefined) {
          return result
        }
      }
    }
  }

console.log(nodeWithIdHasChildren(myObj, "5e590df71bbc71000118c10b"));

11
  • Use a recursive function. Commented Apr 15, 2020 at 14:42
  • @Bergi Thanks for your suggestion. I have tried but not working for me may be i am missing something. Commented Apr 15, 2020 at 14:54
  • Please edit your question to include the code you tried, otherwise we cannot help you find the problem with it. Commented Apr 15, 2020 at 14:55
  • @Bergi i have included my code. Commented Apr 15, 2020 at 15:02
  • You'll want to return the child, not its children, I suppose? The tests for testing whether the child has children are superflous then. If you remove these if statements, the scope of result will be correct as well. Commented Apr 15, 2020 at 15:06

3 Answers 3

1

Use simple recursion

function findDeepById(node, id) {
  if (node.id === id) return node;
  if (node.children) {
    for(const child of node.children){
      const match = findDeepById(child, id);
      if (match) return match;
    }
  }
}

const myObj = {
  "id": "5e6b8961ba08180001a10bb6",
  "children": [{
    "id": "5e6b8961ba08180001a10bb7",
    "refrenceId": "SEC-02986",
    "children": [{
        "id": "5e58d7bc1bbc71000118c0dc"
      },
      {
        "id": "5e58d7bc1bbc71000118c0dd",
        "refrenceId": "SKU-00343"
      },
      {
        "id": "5e590d571bbc71000118c102",
        "refrenceId": "SKU-05290"
      },
      {
        "id": "5e590df71bbc71000118c109",
        "children": [{
            "id": "5e590df71bbc71000118c10a"
          },
          {
            "id": "5e590df71bbc71000118c10b",
            "refrenceId": "SKU-00444"
          },
          {
            "id": "5e5cb9428ae591000177c0f6"
          }
        ]
      },
      {
        "id": "5e81899f0bab450001dcfc1d",
        "refrenceId": "SEC-03260"
      },
      {
        "id": "5e81c4b51503860001f97f6c",
        "refrenceId": "SEC-03267",
        "children": [{
            "id": "5e8ad5175d374200014edb3a",
            "refrenceId": "SEC-03409",
            "children": [{
              "id": "5e8f28882d94c1000156bebe"
            }]
          },
          {
            "id": "5e8ad5175d374200014edb3c",
            "refrenceId": "SEC-03410"
          },
          {
            "id": "5e8f29082d94c1000156bec6",
            "refrenceId": "SEC-03495"
          }
        ]
      }
    ]
  }]
};

function findDeepById(node, id) {

  if (node.id === id) return node;
  if (node.children) {
    for(const child of node.children){
      const match = findDeepById(child, id);
      if (match) return match;
    }
  }
}

console.log(findDeepById(myObj, "5e590df71bbc71000118c10b"));

Sign up to request clarification or add additional context in comments.

Comments

0

In short, this part was the biggest problem:

if (child.id === id) {

    if (Array.isArray(child.children) && child.children.length > 0) {
      return child;
    }
  }

You've found your object, why look for its children?


ORIGINAL ANSWER/WORKING SOLUTION

For start, you need to make your original object iterable because that's what your function expects, I've done so by simply making it an array like nodeHasChildren([myObj], ... when calling the function. Then, after some cleanup and fixing the logic mentioned above, we get this (added relevant comments to the code below):

myObj = {
  "id": "5e6b8961ba08180001a10bb6",
  "children": [{
    "id": "5e6b8961ba08180001a10bb7",
    "refrenceId": "SEC-02986",
    "children": [{
        "id": "5e58d7bc1bbc71000118c0dc"
      },
      {
        "id": "5e58d7bc1bbc71000118c0dd",
        "refrenceId": "SKU-00343"
      },
      {
        "id": "5e590d571bbc71000118c102",
        "refrenceId": "SKU-05290"
      },
      {
        "id": "5e590df71bbc71000118c109",
        "children": [{
            "id": "5e590df71bbc71000118c10a"
          },
          {
            "id": "5e590df71bbc71000118c10b",
            "refrenceId": "SKU-00444"
          },
          {
            "id": "5e5cb9428ae591000177c0f6"
          }
        ]
      },
      {
        "id": "5e81899f0bab450001dcfc1d",
        "refrenceId": "SEC-03260"
      },
      {
        "id": "5e81c4b51503860001f97f6c",
        "refrenceId": "SEC-03267",
        "children": [{
            "id": "5e8ad5175d374200014edb3a",
            "refrenceId": "SEC-03409",
            "children": [{
              "id": "5e8f28882d94c1000156bebe"
            }]
          },
          {
            "id": "5e8ad5175d374200014edb3c",
            "refrenceId": "SEC-03410"
          },
          {
            "id": "5e8f29082d94c1000156bec6",
            "refrenceId": "SEC-03495"
          }
        ]
      }
    ]
  }]
}


function nodeHasChildren(children, id) {
  for (const child of children) {
    if (child.id === id) { 
          // solution found, no need to do anything else
          console.log("SOLUTION: ");
          return child;
    } else {
      // check if it has children and iterate over them recursively
      if (Array.isArray(child.children) && child.children.length > 0)
        var result = nodeHasChildren(child.children, id);
      // check if the result was found in children in the line above
      if (result != undefined)
        return result;
    }
  }
}
console.log(nodeHasChildren([myObj], "5e590df71bbc71000118c10b"));
console.log(nodeHasChildren([myObj], "5e8ad5175d374200014edb3c"));

Comments

0

We now use object-scan for simple data processing tasks. It's pretty awesome once you wrap your head around it. Here is how you could answer your questions

// const objectScan = require('object-scan');

const find = (id, input) => objectScan(['**'], {
  rtn: 'value',
  abort: true,
  filterFn: ({ value }) => value.id === id
})(input);

const myObj = { id: '5e6b8961ba08180001a10bb6', children: [{ id: '5e6b8961ba08180001a10bb7', refrenceId: 'SEC-02986', children: [{ id: '5e58d7bc1bbc71000118c0dc' }, { id: '5e58d7bc1bbc71000118c0dd', refrenceId: 'SKU-00343' }, { id: '5e590d571bbc71000118c102', refrenceId: 'SKU-05290' }, { id: '5e590df71bbc71000118c109', children: [{ id: '5e590df71bbc71000118c10a' }, { id: '5e590df71bbc71000118c10b', refrenceId: 'SKU-00444' }, { id: '5e5cb9428ae591000177c0f6' }] }, { id: '5e81899f0bab450001dcfc1d', refrenceId: 'SEC-03260' }, { id: '5e81c4b51503860001f97f6c', refrenceId: 'SEC-03267', children: [{ id: '5e8ad5175d374200014edb3a', refrenceId: 'SEC-03409', children: [{ id: '5e8f28882d94c1000156bebe' }] }, { id: '5e8ad5175d374200014edb3c', refrenceId: 'SEC-03410' }, { id: '5e8f29082d94c1000156bec6', refrenceId: 'SEC-03495' }] }] }] };

console.log(find('5e8ad5175d374200014edb3a', myObj));
/* =>
{ id: '5e8ad5175d374200014edb3a',
  refrenceId: 'SEC-03409',
  children: [ { id: '5e8f28882d94c1000156bebe' } ] }
*/
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>

Disclaimer: I'm the author of object-scan

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.