2017-11-01 15 views
2

フラットなJSONをツリー構造に変換しようとしていますが、これが可能かどうか不思議です。私の問題を解決する助けがあれば幸いです。IDなしの階層/ツリーへのJSONフラット

以下は、私が現在試しているもので、作業中です。これは最初の子どもの集合を正常に取得するだけで、子どもです。私はそれをこの点に合格させることができませんでした。私はこれが可能でないかもしれないことを恐れる。

私が始めた前に私は根を知っています。私はそれが可能でなければならないと思います。このケースでは、ルートは「自動軍用ヘルスシステム機能を提供する」である。

JSONは、のように見える終わるでしょうツリー:ここ

{ "name": "Provide Automated Military Health Systems Functions", "children": [ { "name": "Provide Infrastructure Support Functions", "children": [ "name": "Provide Data Management Functions" "children": [etc, etc] ] }, { "name": "Provide Clinical Support Functions", "children": [etc etc] }, { "name": "Provide Non-Clinical Support Functions", "children": [etc etc] } ] }

は私ものオフに取り組んできたバイオリンです:http://jsfiddle.net/ydgbkv39/

フィドルは、最初の2のコンソール印刷を行いますレベルを超えているようには思えません。

誰かが私を助けてくれることを願っています。

var data = [ 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Infrastructure Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Clinical Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Non-Clinical Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Data Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Maintenance Utilities Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Business Rules Execution Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide MHS Health Portal Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Security Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Care Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Nutrition Information Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Healthcare Specialty Services Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Lab Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Pharmacy Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Blood Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Medical Imagery Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Operations Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Order Results Care Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Medical Orders Maintenance Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Episodes of Care Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Executive Decision Support Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Manage Family Support Process Workflow (BEA)" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Health Records Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Resource Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Medical Readiness Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Population Health Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Medical Logistics Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Patient Directory Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Provider Information Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Patient Administration Functions" 
 
    } 
 
]; 
 

 
Array.prototype.diff = function(a) { 
 
    return this.filter(function(i) {return a.indexOf(i) < 0;}); 
 
}; 
 

 
var upstreamArr = []; 
 
var downstreamArr = []; 
 
data.forEach(function (a) { 
 
\t upstreamArr.push(a.Upstream); 
 
    downstreamArr.push(a.Downstream); 
 
}, {}); 
 

 
var root = upstreamArr.diff(downstreamArr); 
 
root = root[0]; 
 

 
var tree = {}; 
 
tree.name = root; 
 
tree.children = []; 
 

 
data.forEach(function (a) { 
 
\t if(a.Upstream === root) { 
 
    \t if(tree.children.indexOf(a.Downstream) === -1) { 
 
    \t tree.children.push(a.Downstream); 
 
    } 
 
    } 
 
}, {}); 
 

 
function buildTree(d) { 
 
\t if(d.children.length > 0) { 
 
    \t for(var i = 0; i < d.children.length; i++) { 
 
    \t findKids(d, d.children[i]); 
 
    } 
 
    } 
 
    return d; 
 
} 
 

 
function findKids(d, child) { 
 
    let obj = {}; 
 
    obj.children = []; 
 
\t data.forEach(function (a) { 
 
     if(a.Upstream === child) { 
 
     \t obj.name = child; 
 
     if(obj.children.indexOf(a.Downstream) === -1) { 
 
      obj.children.push(a.Downstream); 
 
     } 
 
     } 
 
    }, {}); 
 

 
\t var ind = d.children.indexOf(child); 
 
\t return d.children[ind] = obj; 
 
    
 
} 
 

 

 
/*function eachRecursive(obj) { 
 
    for (var k in obj) { 
 
     if (typeof obj[k] == "object" && obj[k] !== null) { 
 
     \t eachRecursive(obj[k]); 
 
     } else { 
 
     
 
     } 
 
    } 
 
}*/ 
 

 
console.log(buildTree(tree));

+0

ビルトインされているため、タイプするだけのコードの評論家として、あなたは 'Array.prototype.diff'を変更することは避けてください。詳細については、[この回答を見る](https://stackoverflow.com/a/948379/266535)を参照してください。 – styfle

答えて

1

すべてのノードを「フラット」オブジェクト(各アイテムの名前はフラットオブジェクトのキー)に格納することによって、それらのノードを追跡することができます。フラットオブジェクトに名前がまだ存在しない場合は作成します。それ以外の場合は、参照を使用して子を追加します。

var data = [ 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Data Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Maintenance Utilities Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Business Rules Execution Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide MHS Health Portal Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Security Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Care Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Nutrition Information Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Healthcare Specialty Services Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Lab Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Pharmacy Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Blood Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Medical Imagery Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Operations Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Order Results Care Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Medical Orders Maintenance Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Episodes of Care Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Executive Decision Support Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Manage Family Support Process Workflow (BEA)" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Health Records Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Resource Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Medical Readiness Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Population Health Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Medical Logistics Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Patient Directory Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Provider Information Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Patient Administration Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Infrastructure Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Clinical Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Non-Clinical Support Functions" 
 
    } 
 
]; 
 

 
var tree = {}, flat = {}; 
 

 
var setRoots = function(data){ 
 
    var unique = {}; 
 
    data.forEach(function(item){ 
 
    unique[item.Upstream] = true; 
 
    }); 
 
    data.forEach(function(item){ 
 
    if(unique[item.Downstream]){ 
 
     delete unique[item.Downstream]; 
 
    } 
 
    }); 
 
    var keys = Object.keys(unique), rootName = data[0].Upstream; 
 
    if(keys.length == 1){ 
 
    rootName = keys[0]; 
 
    } 
 
    tree = {name: rootName}; 
 
    flat[rootName] = tree; 
 
} 
 
var addItemToTree = function(item){ 
 
    var parent = flat[item.Upstream], child = flat[item.Downstream]; 
 
    if(!parent){ 
 
    parent = flat[item.Upstream] = { name: item.Upstream } 
 
    } 
 
    if(!child){ 
 
    child = flat[item.Downstream] = { name: item.Downstream }; 
 
    } 
 
    if(!parent.children){ 
 
    parent.children = []; 
 
    } 
 
    parent.children.push(child); 
 
} 
 
setRoots(data); 
 
data.forEach(addItemToTree); 
 
console.log(tree);

+0

これは、ルートノードが配列の最初の要素である限り、完全に機能します。私は子供のプロパティのための空の配列を構築しないので、私は他の答えの代わりにこの答えを選んだ。 – CStreet

+0

私は、注文ではなくデータに基づいてルートを把握するために私の答えを更新しました。 –

+0

'forEach'の中で' indexOf'を使うと、このアルゴリズムはO(n^2)になります。大規模なデータセットの場合、この回答は私のO(n)回答よりもかなり遅くなる可能性があります。 – styfle

2

あなたは価値の鍵(この場合は「名前」)(この場合、ツリーノード)をマッピングするためにオブジェクトを使用する必要があります。

あなたはそれが以下の動作を確認することができますので、私は私の機能の名前:

var data = [ 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Infrastructure Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Clinical Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Automated Military Health Systems Functions", 
 
    "Downstream": "Provide Non-Clinical Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Data Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Maintenance Utilities Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Business Rules Execution Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide MHS Health Portal Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Infrastructure Support Functions", 
 
    "Downstream": "Provide Security Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Care Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Nutrition Information Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Healthcare Specialty Services Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Lab Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Pharmacy Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Blood Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Medical Imagery Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Operations Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Order Results Care Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Medical Orders Maintenance Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Clinical Support Functions", 
 
    "Downstream": "Provide Episodes of Care Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Executive Decision Support Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Manage Family Support Process Workflow (BEA)" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Health Records Support Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Resource Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Medical Readiness Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Population Health Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Medical Logistics Management Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Patient Directory Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Provider Information Functions" 
 
    }, 
 
    { 
 
    "Upstream": "Provide Non-Clinical Support Functions", 
 
    "Downstream": "Provide Patient Administration Functions" 
 
    } 
 
]; 
 

 

 
var nameToNode = {}; 
 

 
function getNodeByName(name) { 
 
    if (!nameToNode[name]) { 
 
    nameToNode[name] = { name: name, children: [] }; 
 
    } 
 
    return nameToNode[name]; 
 
} 
 

 
function getRootNode() { 
 
    for (var name in nameToNode) { 
 
    if (nameToNode[name].children.length > 0) { 
 
     return nameToNode[name]; 
 
    } 
 
    } 
 
} 
 

 
function buildTree() { 
 
    data.forEach(o => { 
 
    var up = getNodeByName(o.Upstream); 
 
    var down = getNodeByName(o.Downstream); 
 
    up.children.push(down); 
 
    }); 
 
} 
 

 
buildTree(); 
 
var root = getRootNode(); 
 
console.log(root);

getRootNode関数は、元のすべてのレコードが単一のツリーを形成する前提としています。複数のルートノードを持つフォレストが必要な場合は、ロジックを少し変更する必要があります。

+0

これは、ルートノードが配列内の最初の要素である限り、完全に機能します。代わりにもう一つの答えを選んだのは、子プロパティの空の配列を作成しなかったからです。しかし、この答えは素晴らしいものでした。 – CStreet