Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

157
Views
How to aggregate a tree structure programmatically from config-like parent-child array items?

I'd like to change my javascript object structure, into an object which is like hierarchy tree patern object, this is my object:

let input = [
  {'id':1 ,'pid' : 0},
  {'id':2 ,'pid' : 1},
  {'id':3 ,'pid' : 2},
  {'id':4 ,'pid' : 2},
  {'id':5 ,'pid' : 3},
  {'id':6 ,'pid' : 3},
  {'id':7 ,'pid' : 4},
  {'id':8 ,'pid' : 4},
  {'id':9 ,'pid' : 4}
];

and found this snippet on the internet and it actually works well (i forgot who made it, thank you so much anyway)

let input = [
{'id':1 ,'pid' : 0},
{'id':2 ,'pid' : 1},
{'id':3 ,'pid' : 2},
{'id':4 ,'pid' : 2},
{'id':5 ,'pid' : 3},
{'id':6 ,'pid' : 3},
{'id':7 ,'pid' : 4},
{'id':8 ,'pid' : 4},
{'id':9 ,'pid' : 4}
];

let register = {};

let output = {};

for (let el of input) {
  el = Object.assign({}, el);
  register[el.id] = el;
 
  if (!el.pid) { 
    output[el.id] = el;
  } else { 
    register[el.pid][el.id] = el
  }

  delete el.pid;
  delete el.id
}

document.body.innerHTML = "<pre>" + (JSON.stringify(output, undefined, 2))

something i didn't expected came up when i change the PID value with the id from below, i mean, from this {'id':4 ,'pid' : 2} into this {'id':4 ,'pid' : 9}, the result is register[el.pid] is undefined

please help to fix this, thanks in advance

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Aggregating a tree programmatically from parent-child config-like items is possible even when such items are not in perfect order as long as such relationships are valid, thus representable.

Circular parent child references, like what the OP creates/triggers when changing { 'id': 4, 'pid': 2 } to { 'id': 4, 'pid': 9 }, loose the linkage into an already representable overall tree structure. Thus such references are invalid and any other valid substructure which is linked to the former is lost as well.

The above claim proves itself with the next provided example code ...

function aggregateTree( 
  { index = {}, result = {} }, // accumulator.
  { id, pid },                 // parent child config.
) {
  const childItem = (index[id] ??= { [id]: {} });
  const parentItem = (pid !== 0)
    && (index[pid] ??= { [pid]: {} })
    || null;
  const node = (parentItem !== null)
    && parentItem[pid] // programmatically build partial trees.
    || result // assign partial tree references at root/resul level.

  Object.assign(node, childItem);

  return { index, result };
}

console.log('unordered but valid parent child relationships ...', [

  { 'id': 1 ,'pid': 0 },
  { 'id': 2 ,'pid': 1 },
  { 'id': 3 ,'pid': 2 },

  { 'id': 12, 'pid': 0 },

  { 'id': 11, 'pid': 6 },
  { 'id': 10, 'pid': 6 },

  { 'id': 4, 'pid': 5 },

  { 'id': 5 ,'pid': 3 },
  { 'id': 6 ,'pid': 3 },

  { 'id': 7 ,'pid': 4 },
  { 'id': 8 ,'pid': 4 },
  { 'id': 9 ,'pid': 4 }

].reduce(aggregateTree, { result: {} }).result);

console.log('ordered but partially invalid parent child relationships ...', [

  // circular references like 4 to 9 and 9 to 4,
  // thus not being linked to the overall tree,
  // can not be aggregated and displayed.

  { 'id': 1, 'pid': 0 },
  { 'id': 2, 'pid': 1 },
  { 'id': 3, 'pid': 2 },

  { 'id': 4, 'pid': 9 }, // circular thus disconnected.
  // { 'id': 9, 'pid': 4 },

  { 'id': 5, 'pid': 3 },
  { 'id': 6, 'pid': 3 },

  { 'id': 7, 'pid': 4 }, // lost due to being linked to a circular reference.
  { 'id': 8, 'pid': 4 }, // lost due to being linked to a circular reference.

  { 'id': 9, 'pid': 4 }, // circular thus disconnected.
  // { 'id': 4, 'pid': 9 },

].reduce(aggregateTree, { result: {} }).result);
.as-console-wrapper { min-height: 100%!important; top: 0; }

about 4 years ago · Juan Pablo Isaza Report

0

Well, you can not move the parent to it's own children. This works only in time travel novels/movies.


For creating a tree without deleting properties, you could take a single loop and take the id and parent as well and as result the object with the root parent 0.

This approach works with unsorted data as well.

const
    input = [{ id: 1, pid: 0 }, { id: 2, pid: 1 }, { id: 3, pid: 2 }, { id: 4, pid: 2 }, { id: 5, pid: 3 }, { id: 6, pid: 3 }, { id: 7, pid: 4 }, { id: 8, pid: 4 }, { id: 9, pid: 4 }],
    tree = {};

for (const { id, pid } of input) {
    tree[pid] ??= {};
    tree[id] ??= {};
    tree[pid][id] ??= tree[id];
}

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

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!