【问题标题】:Generate tree hierarchy using nodes and links json [closed]使用节点和链接 json 生成树层次结构 [关闭]
【发布时间】:2017-03-28 06:46:12
【问题描述】:

我想要将节点和链接 json 转换为树 json 的 javascript 函数。

这里是节点和链接 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, target: 1, value: 1} :- source:0 表示节点 [0] 和 target:1 表示节点[1]

在上面的 json 转换之后,树的层次结构如下所示:

[
  {
    "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"
      }
    ]
  }
];

谢谢。

【问题讨论】:

  • 你怎么知道谁是谁的孩子,谁是谁的父母?
  • 我打赌 OP 会说 "by the value of name".
  • 您似乎希望我们为您编写一些代码。虽然许多用户愿意为陷入困境的编码人员编写代码,但他们通常只有在发布者已经尝试自己解决问题时才会提供帮助。展示这项工作的一个好方法是包含您迄今为止编写的代码(形成minimal reproducible example)、示例输入(如果有的话)、预期输出和实际获得的输出(输出、回溯、 ETC。)。您提供的详细信息越多,您可能收到的答案就越多。检查tourHow to Ask
  • @brk 我已经更新了我的问题,请检查一下。如果有任何疑问,请告诉我。谢谢。

标签: javascript arrays json d3.js


【解决方案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; }

【讨论】:

    【解决方案2】:

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

    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);
    

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-04
      相关资源
      最近更新 更多