1

I have some issues converting a flat list to hierarchical. Im trying to visualize d3.js tree chart from below data. Each node has two child objects described in fams array.

I found something similar to my problem here, but I can't get it working with two parent nodes Converting flat structure to hierarchical

This is what i want to archive https://bl.ocks.org/d3noob/8329404

I hope someone can point me in the right direction, thanks in advance.

let nodes = [
{ id: 'N001', fam: 'F001' },
{ id: 'N002', fam: 'F002' },
{ id: 'N003', fam: 'F003' },
{ id: 'N004', fam: 'F004' },
{ id: 'N005', fam: 'F005' },
{ id: 'N006', fam: 'F006' },
{ id: 'N007', fam: 'F007' },
{ id: 'N008', fam: 'F008' },
{ id: 'N009', fam: 'F009' },
{ id: 'N010', fam: 'F010' },
{ id: 'N011', fam: 'F011' }
];

let fams = [
{ id: 'F001', p1: 'N002', p2: 'N003' },
{ id: 'F002', p1: 'N004', p2: 'N005' },
{ id: 'F003', p1: 'N006', p2: 'N007' },
{ id: 'F004', p1: 'N008', p2: 'N009' },
{ id: 'F005', p1: 'N010', p2: 'N011' }
];

// Expected output
let finalData = [
{
id: 'N001',
children: [
  {
    id: 'N002',
    fam: 'F002',
    children: [
      {
        id: 'N004',
        fam: 'F004',
        children: [
          { id: 'N008', fam: 'F008' },
          { id: 'N009', fam: 'F009' }
        ]
      },
      {
        id: 'N005',
        fam: 'F005',
        children: [
          { id: 'N010', fam: 'F010' },
          { id: 'N011', fam: 'F011' }
        ]
      }
    ]
  },
  {
    id: 'N003',
    fam: 'F003',
    children: [
      { id: 'N006', fam: 'F006' },
      { id: 'N007', fam: 'F007' }
    ]
  }
]
}
];
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171
Pim
  • 15
  • 1
  • 5
  • It looks like you've forgotten to add the code you've issues with ..? Notice also, that this question has nothing to do with [JSON](https://www.json.org/json-en.html). – Teemu Feb 26 '20 at 07:06
  • Not related: congratulation on the D3 question number 35000. Human beings like those round numbers, for whatever reason. – Gerardo Furtado Feb 26 '20 at 08:06

1 Answers1

1

One possible solution is looping the nodes array to create a new property (parentId), based on fams, which describes the parent (null if none):

nodes.forEach(function(d) {
  const fam = fams.find(function(e) {
    return e.p1 === d.id || e.p2 === d.id
  });
  d.parentId = fam ? nodes.find(function(e) {
    return e.fam === fam.id;
  }).id : null;
});

After that, creating the hierarchical structure with d3.stratify() will be quite trivial:

const stratify = d3.stratify()(nodes);

Here is the demo (use your browser's console to check the result, not the S.O. snippet console):

let nodes = [{
    id: 'N001',
    fam: 'F001'
  },
  {
    id: 'N002',
    fam: 'F002'
  },
  {
    id: 'N003',
    fam: 'F003'
  },
  {
    id: 'N004',
    fam: 'F004'
  },
  {
    id: 'N005',
    fam: 'F005'
  },
  {
    id: 'N006',
    fam: 'F006'
  },
  {
    id: 'N007',
    fam: 'F007'
  },
  {
    id: 'N008',
    fam: 'F008'
  },
  {
    id: 'N009',
    fam: 'F009'
  },
  {
    id: 'N010',
    fam: 'F010'
  },
  {
    id: 'N011',
    fam: 'F011'
  }
];

let fams = [{
    id: 'F001',
    p1: 'N002',
    p2: 'N003'
  },
  {
    id: 'F002',
    p1: 'N004',
    p2: 'N005'
  },
  {
    id: 'F003',
    p1: 'N006',
    p2: 'N007'
  },
  {
    id: 'F004',
    p1: 'N008',
    p2: 'N009'
  },
  {
    id: 'F005',
    p1: 'N010',
    p2: 'N011'
  }
];

nodes.forEach(function(d) {
  const fam = fams.find(function(e) {
    return e.p1 === d.id || e.p2 === d.id
  });
  d.parentId = fam ? nodes.find(function(e) {
    return e.fam === fam.id;
  }).id : null;
});

const stratify = d3.stratify()(nodes);

console.log(stratify)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Gerardo Furtado
  • 100,839
  • 9
  • 121
  • 171