Javascript D3:使用嵌套函数将具有父键的平面数据转换为层次结构

Javascript D3:使用嵌套函数将具有父键的平面数据转换为层次结构,javascript,json,nested,operators,d3.js,Javascript,Json,Nested,Operators,D3.js,我相信有一个非常简单优雅的方法可以做到这一点,但我不太明白。我有一些输入数据如下所示: [ {id: 1, name: "Peter"}, {id: 2, name: "Paul", manager: 1}, {id: 3, name: "Mary", manager: 1}, {id: 4, name: "John", manager: 2}, {id: 5, name: "Jane", manager: 2} ] 如果可能的话,我想使用d3.js nest操作符来获取层次结构布局中使用的结

我相信有一个非常简单优雅的方法可以做到这一点,但我不太明白。我有一些输入数据如下所示:

[
{id: 1, name: "Peter"},
{id: 2, name: "Paul", manager: 1},
{id: 3, name: "Mary", manager: 1},
{id: 4, name: "John", manager: 2},
{id: 5, name: "Jane", manager: 2}
]
如果可能的话,我想使用d3.js nest操作符来获取层次结构布局中使用的结构。像这样:

[ 
   {name: "Peter", children: [
          {name:"Paul", children: [
              {name:"John"},
              {name:"Jane"}
          ]},
          {name:"Mary"}
      ]
   }
]

此处不能使用嵌套运算符,因为嵌套生成固定的层次结构:输出层次结构中的级别数与指定的关键函数数相同

也就是说,您可以编写自己的生成树的函数。假设根节点是输入数组中的第一个节点,则可以创建从id到节点的映射,然后惰性地构造树

function tree(nodes) {
  var nodeById = {};

  // Index the nodes by id, in case they come out of order.
  nodes.forEach(function(d) {
    nodeById[d.id] = d;
  });

  // Lazily compute children.
  nodes.forEach(function(d) {
    if ("manager" in d) {
      var manager = nodeById[d.manager];
      if (manager.children) manager.children.push(d);
      else manager.children = [d];
    }
  });

  return nodes[0];
}

如果您知道节点是按顺序列出的,以便管理者在其报告之前出现,那么您可以简化代码,使其只迭代一次。

非常感谢,这非常有帮助。实际上,我从树的顶部开始,(1)基于manager(数组字典)创建查找,(2)从已知根开始,递归地将子级添加到每个报告中。