将平面数组转换为分层数组

Convert flat arrays to hierarchical

我在将平面列表转换为分层列表时遇到了一些问题。 我正在尝试从下面的数据中可视化 d3.js 树状图。 每个节点都有 fams 数组中描述的两个子对象。

我在这里发现了一些与我的问题类似的东西,但我无法让它与两个父节点一起工作

这是我要存档的内容https://bl.ocks.org/d3noob/8329404

我希望有人能指出我正确的方向,在此先感谢。

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' }
    ]
  }
]
}
];

一个可能的解决方案是循环 nodes 数组以创建一个新的 属性 (parentId),基于 fams,它描述父 (null 如果 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;
});

之后,使用 d3.stratify() 创建层次结构将非常简单:

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

这是演示(使用浏览器的控制台检查结果,而不是 S.O。代码段控制台):

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>