2017-03-28 2 views
-1

ノードを変換し、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} 
     ] 
    } 

はここで、ノードの配列インデックスは「ソース」と「ターゲット」を持つ配列をリンクします。ここでは

は、ノードとリンクJSONです。例えばについて {源:0ターゲット:1、値:1} - ソース:1 [1]

上記変換した後のノードを意味する:0ノード[0]と標的手段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" 
     } 
    ] 
    } 
]; 

ありがとうございます。次のように

+0

? – brk

+0

私はOPが '' name' "*の値で*"言うつもりです。 –

+0

ようこそスタックオーバーフロー! [どうすればよい質問ができますか?](// stackoverflow.com/help/how-to-ask)と[最小限の完全かつ検証可能なサンプルを作成する方法](// stackoverflow.com/ヘルプ/ mcve)。 – Olaia

答えて

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機能が見えますあなたはすべてのnodesを繰り返すことによって、ツリーを構築し、すべてのlinksを反復することにより、その後、キーとインデックスと名前だけを持つオブジェクトを生成し、親と子、ツリー構造でノードを追加することができ

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

:このようなが生成される。

次に、オブジェクト内の子にフラグを立てる必要があります。子ノードは、後で非子ノードのみを返します。あなたは&誰の親であるの子が誰であるか知っていますか

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

関連する問題