使用节点和链接json生成树层次结构

时间:2017-03-28 06:46:13

标签: javascript arrays json d3.js

我想要javascript函数转换节点并将json链接到树json。

这是节点和链接JSON:

    {
      "nodes": [
         {name: "Top Level", group: 1},
         {name: "Level 2: A", group: 1},
         {name: "Son of A", group: 1},
         {name: "Daughter of A", group: 1},
         {name: "Level 2: B", group: 1}
      ],
      "links": [
         {source: 0, target: 1, value: 1},
         {source: 0, target: 4, value: 1},
         {source: 1, target: 2, value: 1},
         {source: 1, target: 3, value: 1}
      ]
   }

这里链接的数组有" source"和"目标"是节点数组索引。 例如{来源:0 目标:1 ,值:1}: - 来源:0 表示节点[0]和 target:1 表示节点[1]

转换为json之后,Tree层次结构如下所示:

[
  {
    "name": "Top Level",
    "parent": "null",
    "children": [
      {
        "name": "Level 2: A",
        "parent": "Top Level",
        "children": [
          {
            "name": "Son of A",
            "parent": "Level 2: A"
          },
          {
            "name": "Daughter of A",
            "parent": "Level 2: A"
          }
        ]
      },
      {
        "name": "Level 2: B",
        "parent": "Top Level"
      }
    ]
  }
];

感谢。

2 个答案:

答案 0 :(得分:1)

你可以通过迭代所有nodes来构建一个树,并生成一个索引为关键而且只是名称的对象,然后通过迭代所有links并在父节点和子节点上追加节点,其中一棵树结构生成。

然后,您需要在对象中标记子对象,稍后只返回非子节点。



var data = { nodes: [{ name: "Top Level", group: 1 }, { name: "Level 2: A", group: 1 }, { name: "Son of A", group: 1 }, { name: "Daughter of A", group: 1 }, { name: "Level 2: B", group: 1 }], links: [{ source: 0, target: 1, value: 1 }, { source: 0, target: 4, value: 1 }, { source: 1, target: 2, value: 1 }, { source: 1, target: 3, value: 1 }] },
    tree = function (object) {
        var o = {}, children = {};

        object.nodes.forEach(function (a, i) {
            o[i] = { name: a.name };
        });

        object.links.forEach(function (a) {
            o[a.target].parent = o[a.source].name;
            o[a.source].children = o[a.source].children || [];
            o[a.source].children.push(o[a.target]);
            children[a.target] = true;
        });

        return Object.keys(o).filter(function (k) {
            return !children[k];
        }).map(function (k) {
            return o[k];
        });
    }(data);

console.log(tree);

.as-console-wrapper { max-height: 100% !important; top: 0; }




答案 1 :(得分:0)

一个简单的解决方案如下:

var data; // parse the JSON into here
var buildNode = function(index) {

    var children = data.links.filter(function(x) {
        return x.source === index;
    }).map(function(x) {
        return buildNode(x.target);
    });

    //with ES6 you can use .find to get the first matching item, instead of .filter and [0]
    var parent = data.links.filter(function(x) {
        return x.target === index;
    })[0];
    var parentName = parent ? parent.name : undefined;

    return {
        name: data.nodes[index].name,
        parent: parentName,
        children: children
    };
};

var tree = buildNode(0);

NB。首先使用相应的目标和父项生成数组可能更有效,而不是每次都遍历整个数组:

var data; // parse the JSON into here
var nodeTargets = [];
var nodeParents = [];
data.links.forEach(function(x) {
    if (!nodeTargets[x.source]) {
        nodeTargets[x.source] = []
    }
    nodeTargets[x.source].push(x.target);

    nodeParents[x.target] = x.source;
});

这将导致nodeTargets中的以下数组结构:

[
    [1, 4],
    [2, 3]
]

以及nodeParents中的以下内容:

{
    1: 0,
    4: 0,
    2: 1,
    3: 1
}

然后buildNode函数看起来像这样:

var buildNode = function(index) {

    var children = nodeTargets[index].map(function(x) {
        return buildNode(x);
    });

    var parentIndex = nodeParents[index];
    var parentName;
    if (parentIndex !== undefined) {
        parentName = data.nodes[parentIndex].name;
    }

    return {
        name: data.nodes[index].name,
        parent: parentName,
        children: children
    };
};