0

I'm trying to figure out how to construct a hierachy object from some smaller objects that I have. Here's some example data:

{ id: 1, name: 'Jackson', parent: null },
{ id: 2, name: 'Jordan', parent: 1 },
{ id: 3, name: 'Jefferson', parent: 1 },
{ id: 4, name: 'Elvis', parent: 2 },
{ id: 5, name: 'Sally', parent: null },
{ id: 6, name: 'Eric', parent: 4 }

This would be constructed into a HIerarchy object that should look like so:

{ 
  '1': { 
    name: 'Jackson',
    children: {
       '2': {
         name: 'Jordan',
         children: { 
           '4': {
             name: 'Elvin',
             children: { 
               '6': {
                 name: 'Eric',
                 children: { }
             }  
           }
         } },
       '3': {
         name: 'Jefferson',
         children: { } }
     }
  },
  '5': {
     name: 'Sally',
     children: { } 
  }

I'm really having a hard time figuring this out other then doing a for-loop for every id. (Ie: find all with null parent, find all with 1 parent, find all with 2 parent, etc...)

9
  • 1
    I'm not sure why you have an object instead of array for children. Care to elaborate? Commented Jan 30, 2017 at 23:03
  • Possible duplicate of Convert from self-reference array into nested array in tree Commented Jan 30, 2017 at 23:03
  • Probably better to do this server side? Commented Jan 30, 2017 at 23:06
  • @AlGoreRhythm Javascript is capable of server-side code. Commented Jan 30, 2017 at 23:10
  • 1
    Not necessarily, but that depends on what your endgame is with this. If there's a UI involved then there's likely no problem doing a lookup because you'd have the object reference right there. Commented Jan 30, 2017 at 23:14

1 Answer 1

1

Here's my take on how to do this.

Create an object that will hold references to all the other objects, based on their key. This allows us to get a reference to each object by its key at the moment we need it as a parent of another element:

let register = {};

Create our output object:

let output = {};

Now let's go through each object in the array and add it to the structure:

// loop through the array
for (let el of elements) {
  // clone the element, so we don't modify the original array
  el = Object.assign({}, el);

  // insert the clone into the register
  register[el.id] = el;

  if (!el.parent) { // if no parent is set, add it to the top level
    output[el.id] = el;
  } else { // otherwise, add it as a child of whatever the parent is
    register[el.parent].children[el.id] = el;
  }

  // add a children property
  el.children = {};
  // remove the parent property
  delete el.parent;
}

Remember that objects are always stored by reference, so modifying an object in the register object also modifies it in the output object.

Below is a working example.

let input = [{
  id: 1,
  name: 'Jackson',
  parent: null
}, {
  id: 2,
  name: 'Jordan',
  parent: 1
}, {
  id: 3,
  name: 'Jefferson',
  parent: 1
}, {
  id: 4,
  name: 'Elvis',
  parent: 2
}, {
  id: 5,
  name: 'Sally',
  parent: null
}, {
  id: 6,
  name: 'Eric',
  parent: 4
}];

let register = {};

let output = {};

// loop through the array
for (let el of input) {
  // clone the element, so we don't modify the original array
  el = Object.assign({}, el);

  // insert the clone into the register
  register[el.id] = el;

  if (!el.parent) { // if no parent is set, add it to the top level
    output[el.id] = el;
  } else { // otherwise, add it as a child of whatever the parent is
    register[el.parent].children[el.id] = el;
  }

  // add a children property
  el.children = {};
  // remove the parent property
  delete el.parent;
}

console.log(JSON.stringify(output, undefined, 2));

Note that this will not work with circular references, or if the keys are out of order (i.e. the child appears before its parent).

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

1 Comment

This seems to be working for what I need, thanks! I completely forgot that the parent always has to appear first and that's what was causing my confusing implementation with a n^n loop.

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.