复杂的d3.nest()操作

tur*_*tle 11 d3.js

我有一个数组数组,如下所示:

var arrays = [[1,2,3,4,5],
              [1,2,6,4,5],
              [1,3,6,4,5],
              [1,2,3,6,5],
              [1,7,5],
              [1,7,3,5]]
Run Code Online (Sandbox Code Playgroud)

我想使用d3.nest()甚至只是标准的javascript将这些数据转换为我可以与d3.partition一起使用的嵌套数据结构.具体来说,我想创建此处的d3.nest()数据格式.

我想用d3.nest()创建的json对象的级别对应于数组中的索引位置.请注意,d3.partition它位于上述示例数据中所有子数组的第一个位置; 因此,它在树的根部.在阵列中的下一个位置有三个值,flare.json,d3.nest(),和1,因此,根值2有3个孩子.此时树看起来像这样:

      1
    / | \
   2  3  7
Run Code Online (Sandbox Code Playgroud)

在子阵列的第三个位置有四个值3,71.这些孩子将如下进入树中:

            1
        ____|___
       /    |    \
      2     3     7
     / \   /     / \
    3   6 6     3   5
Run Code Online (Sandbox Code Playgroud)

如何使用d3.nest()生成此数据结构?上面显示的示例数据的完整数据结构应如下所示:

   {"label": 1, 
     "children": [
        {"label": 2, "children": [
            {"label": 3, "children": [
                {"label": 4, "children": [
                    {"label": 5}
                ]},
                {"label": 6, "children": [
                    {"label": 5}
                ]}
            ]},
            {"label": 6, "children": [
                {"label": 4, "children": [
                    {"label": 5}
                ]}
            ]},
        {"label": 3, "children": [
            {"label": 6, "children": [
                {"label": 4, "children": [
                    {"label": 5}
                ]}
            ]}
        ]},
        {"label": 7, "children": [
            {"label": 3, "children": [
                {"label": 5}
            ]},
            {"label": 5}
        ]}
      ]}
    ]}
Run Code Online (Sandbox Code Playgroud)

我正在尝试使用类似的东西转换我的数组数据结构(非常错误):

var data = d3.nest()
  .key(function(d, i) { return d.i; })
  .rollup(function(d) { return d.length; })
Run Code Online (Sandbox Code Playgroud)

我已经敲打了一个星期,试图理解如何从阵列数组中产生这种分层数据结构.如果有人可以帮助我,我将非常感激.

@ meetamit在评论中的答案是好的,但在我的情况下,我的树太深,不能重复应用于3数据,所以我无法手动编写这样的函数.

Ame*_*aBR 12

这是一个更简单的函数,for它只使用嵌套的循环来循环遍历每组数组中的所有路径指令.

为了更容易找到具有给定标签的子元素,我实现children了数据对象/关联数组而不是编号数组.如果你想要非常强大,你可以使用d3.map出于该链接所描述的原因,但如果你的标签实际上是整数而不是那个问题.无论哪种方式,它只是意味着当你需要作为一个数组访问子节点时(例如,对于d3布局函数),你必须指定一个函数来从对象的值中创建一个数组 - d3.values(object)效用函数是它适合你.

关键代码:

var root={}, 
    path, node, next, i,j, N, M;

for (i = 0, N=arrays.length; i<N; i++){
    //for each path in the data array 
    path = arrays[i];
    node = root; //start the path from the root

    for (j=0,M=path.length; j<M; j++){
        //follow the path through the tree
        //creating new nodes as necessary

        if (!node.children){ 
            //undefined, so create it:
            node.children = {}; 
        //children is defined as an object 
        //(not array) to allow named keys
        }

        next = node.children[path[j]];
        //find the child node whose key matches
        //the label of this step in the path

        if (!next) {
            //undefined, so create
            next = node.children[path[j]] = 
                {label:path[j]};
        }
        node = next; 
        // step down the tree before analyzing the
        // next step in the path.        
    }    
}
Run Code Online (Sandbox Code Playgroud)

使用您的示例数据数组和基本的聚类树状图表方法实现:http://fiddle.jshell.net/KWc73/

编辑添加:如评论中所述,要使输出看起来完全符合要求:

  1. 从默认根对象的children数组访问数据的根对象.
  2. 使用递归函数循环遍历树,用子数组替换子对象.

像这样:

root = d3.values(root.children)[0];
//this is the root from the original data, 
//assuming all paths start from one root, like in the example data

//recurse through the tree, turning the child
//objects into arrays
function childrenToArray(n){
    if (n.children) {
        //this node has children

        n.children = d3.values(n.children);
        //convert to array

        n.children.forEach(childrenToArray);
        //recurse down tree
    }
}
childrenToArray(root);
Run Code Online (Sandbox Code Playgroud)

更新小提琴:http:
//fiddle.jshell.net/KWc73/1/