4

Please go through this javascript object:

var obj = [{
  id: "A",
  children: [{
    id: "B",
    children: [{
      id: "C",
      children: [{
        id: "D",
        children: [{
          id: "E",
          children: [{
            id: "F"
          }]
        }]
      }, {
        id: "G",
        children: {
          id: "H"
        }
      }]
    }, {
      id: "I"
    }]
  }, {
    id: "J",
    children: [{
      id: "K"
    }]
  }]
}, {
  id: "L"
}, {
  id: "M",
  children: {
    id: "N",
    children: [{
      id: "O"
    }]
  }
}, {
  id: "P"
}];

How to write JavaScript code to recursively parse it and print all the IDs in console so that the output looks like:

A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P

This is how far I could reach. I couldn't think of any logic after that.

for ( i=0 ; i < obj.length ; i++ ){
         var objId = obj[i];
         for( j=i; j<1 ; j++){
             console.log(obj[j].id);
             console.log(obj[j].children[j].id);
         }
     }

I don't understand what logic should be applied here. Do help.

4
  • 7
    Have you tried anything yourself yet? Commented Dec 14, 2016 at 20:33
  • You need to traverse the object in a certain order to get the desired outcome. Look into traversal strategies and pick the appropriate one. Commented Dec 14, 2016 at 20:36
  • 1
    you should use a recursive function. The principle : the function test if object contains a children to call itself on the children ;) Commented Dec 14, 2016 at 20:37
  • ofcourse. for ( i=0 ; i < obj.length ; i++ ){ var objId = obj[i]; for( j=i; j<1 ; j++){ console.log(obj[j].id); console.log(obj[j].children[j].id); } } This is how far I reached, Commented Dec 14, 2016 at 20:37

3 Answers 3

5

You could use an iterative and recursive approach with a depth-first search algorithm.

Edit: Extended for children as object.

var data = [{ id: "A", children: [{ id: "B", children: [{ id: "C", children: [{ id: "D", children: [{ id: "E", children: [{ id: "F" }] }] }, { id: "G", children: { id: "H" } }] }, { id: "I" }] }, { id: "J", children: [{ id: "K" }] }] }, { id: "L" }, { id: "M", children: { id: "N", children: [{ id: "O" }] } }, { id: "P" }];

data.forEach(function iter(a) {
    console.log(a.id);
    if (Array.isArray(a.children)) {
        a.children.forEach(iter);
        return;
    }
    if (a.children && typeof a.children === 'object') { // omit this part
        iter(a.children);                               // if children is
    }                                                   // always an array
});

This version collects all necessary data and returns it in an array.

var data = [{ id: "A", children: [{ id: "B", children: [{ id: "C", children: [{ id: "D", children: [{ id: "E", children: [{ id: "F" }] }] }, { id: "G", children: { id: "H" } }] }, { id: "I" }] }, { id: "J", children: [{ id: "K" }] }] }, { id: "L" }, { id: "M", children: { id: "N", children: [{ id: "O" }] } }, { id: "P" }],
    result = data.reduce(function iter(r, o) {
        r.push(o.id);
        if (Array.isArray(o.children)) {
            return o.children.reduce(iter, r);
        }
        if (o.children && typeof o.children === 'object') { // omit this part
            return iter(r, o.children);                     // if children is
        }                                                   // always an array
        return r;
    }, []);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

7 Comments

Are you fine Nina ? It's the first time you use forEach. I thaught you were a princess of map reduce
The requirements are all about side-effects. Hard to use map when it's about side-effects!
@NinaScholz as always nice answer Nina +1. I am missing the H in the console log though. What if children is an Object and not an Array, or am i missing something here ? Ohh, and the N as well.
Have to ask the OP if this is intentional or accidental. A horrible data structure if intentional!
@DavidDomain, now with H and N.
|
1

You could use the below ES6 function. Note that at two places you did not define children as an array, which I assume is a mistake. If it is indented, I would strongly advise to reconsider, and make it consistent throughout.

function getIds(data) {
    return data.reduce((acc, el) => acc.concat(el.id, getIds(el.children || [])), [])
}

var obj = [{
  id: "A",
  children: [{
    id: "B",
    children: [{
      id: "C",
      children: [{
        id: "D",
        children: [{
          id: "E",
          children: [{
            id: "F"
          }]
        }]
      }, {
        id: "G",
        children: [{
          id: "H"
        }]
      }]
    }, {
      id: "I"
    }]
  }, {
    id: "J",
    children: [{
      id: "K"
    }]
  }]
}, {
  id: "L"
}, {
  id: "M",
  children: [{
    id: "N",
    children: [{
      id: "O"
    }]
  }]
}, {
  id: "P"
}];

console.log(getIds(obj).join('\n'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

3 Comments

Yes, how far I am from being JS ninja. Thank's master
You've modified the input so that children is always an array (which is definitely a better data design, but not what the OP specified).
I wanted to mention that, as I assumed it was an error. I will add this comment to my answer.
0

What you are showing looks like it is asking for a depth first solution, as the order of the ids are clearly alphabetical and they are ordered by first encountered then by depth.

As a result, every id encountered will be collected, and then the deeper ids will be examined. This can, and probably should, be done with recursion.

Here is an example.

  
var obj=[{id:"A",children:[{id:"B",children:[{id:"C",children:[{id:"D",children:[{id:"E",children:[{id:"F"}]}]},{id:"G",children:{id:"H"}}]},{id:"I"}]},{id:"J",children:[{id:"K"}]}]},{id:"L"},{id:"M",children:{id:"N",children:[{id:"O"}]}},{id:"P"}];

var ids = [];//output holder
(function tree(cur){ //recursive function
 for(var i = 0; i < cur.length; i++){ //iterate current set
     ids.push(cur[i].id); //always store id
     if(cur[i].children) tree(cur[i].children); //recurse if children exist
 }
})(obj) //start from the top
    
console.log(ids);

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.