dmx dmx - 1 month ago 9
Javascript Question

How to build data set for D3 In JavaScript?

I am trying to build graph like this :enter image description here. It is basically dependencies tree. Every node has a list of elements it depends on as children (in list), or simple json with name and size (see the structure below). For more details, see this

{
"name": "flare",
"children": [
{
"name": "analytics",
"children": [
{
"name": "cluster",
"children": [
{"name": "AgglomerativeCluster", "size": 3938},
{"name": "CommunityStructure", "size": 3812},
{"name": "HierarchicalCluster", "size": 6714},
{"name": "MergeEdge", "size": 743}
]
},
{
"name": "graph",
"children": [
{"name": "BetweennessCentrality", "size": 3534},
{"name": "LinkDistance", "size": 5731},
{"name": "MaxFlowMinCut", "size": 7840},
{"name": "ShortestPaths", "size": 5914},
{"name": "SpanningTree", "size": 3416}
]
},
{
"name": "optimization",
"children": [
{"name": "AspectRatioBanker", "size": 7074}
]
}
]
},
....
....
}


In my case, I want the same thing, with different set of data. My data look like this in json:

[{
"angular-chart.js@1.0.3": {
"chart.js@2.3.0": {
"chartjs-color@2.0.0": {
"chartjs-color-string@0.4.0": {
"color-name@1.1.1": {}
},
"color-convert@0.5.3": {}
},
"moment@2.15.2": {}
},
"angular@1.5.8": {}
}
},
{
"body-parser@1.15.2": {
"content-type@1.0.2": {},
"bytes@2.4.0": {},
"http-errors@1.5.0": {
"inherits@2.0.1": {},
"statuses@1.3.0": {},
"setprototypeof@1.0.1": {}
},
"debug@2.2.0": {
"ms@0.7.1": {}
},
"depd@1.1.0": {},
"on-finished@2.3.0": {
"ee-first@1.1.1": {}
},
"iconv-lite@0.4.13": {},
"qs@6.2.0": {},
"raw-body@2.1.7": {
"unpipe@1.0.0": {},
"bytes@2.4.0": {},
"iconv-lite@0.4.13": {}
},
"type-is@1.6.13": {
"mime-types@2.1.12": {
"mime-db@1.24.0": {}
},
"media-typer@0.3.0": {}
}
}
}]


as you can see, it it just a array of dependencies. basically, every array element is and element the root node depends on, and has it own dependencies. For example the first element the root depends on is
angular-chart.js@1.0.3
. This json is just saying that:


  1. angular-chart.js > (chart.js and angular@1.5.8).

  2. char.js > (chartjs-color and moment)

  3. chartjs-color-string > (chartjs-color-string and color-convert).

  4. chartjs-color-string > color-name.

  5. color-name > {}, color-convert > {}.

  6. moment > {}

  7. angular > {}



and should became something like this:

{"name": "angular-chart.js@1.0.3",
"children": [
{"name": "angular@1.5.8", "size": 1000},
{"name": "chart.js@2.3.0",
"children": [
{"name": "moment@2.15.2", "size": 1000},
{"name": "chartjs-color@2.0.0",
"children":[
{"name": "chartjs-color-string@0.4.0",
"children":[
{"name": "color-name@1.1.1", "size": 1000}
]
},
{"name": "color-convert@0.5.3", "size": 1000}
]
}
]
}
]
}


Can you please give and algorithm to go from :

{
"angular-chart.js@1.0.3": {
"chart.js@2.3.0": {
"chartjs-color@2.0.0": {
"chartjs-color-string@0.4.0": {
"color-name@1.1.1": {}
},
"color-convert@0.5.3": {}
},
"moment@2.15.2": {}
},
"angular@1.5.8": {}
}
}


TO:

{"name": "angular-chart.js@1.0.3",
"children": [
{"name": "angular@1.5.8", "size": 1000},
{"name": "chart.js@2.3.0",
"children": [
{"name": "moment@2.15.2", "size": 1000},
{"name": "chartjs-color@2.0.0",
"children":[
{"name": "chartjs-color-string@0.4.0",
"children":[
{"name": "color-name@1.1.1", "size": 1000}
]
},
{"name": "color-convert@0.5.3", "size": 1000}
]
}
]
}
]
}


in javascript

Answer

You could use this recursive ES6 function:

function tree(data) {
    return Object.keys(data).map( key => Object.keys(data[key]).length 
        ? { name: key, children: tree(data[key]) }
        : { name: key, size: 1000 }
    );
}
// Sample data
var data = {
  "angular-chart.js@1.0.3": {
    "chart.js@2.3.0": {
      "chartjs-color@2.0.0": {
        "chartjs-color-string@0.4.0": {
          "color-name@1.1.1": {}
        },
        "color-convert@0.5.3": {}
      },
      "moment@2.15.2": {}
    },
    "angular@1.5.8": {}
  }
};
// conversion
var arr = tree(data);
// output
console.log(arr);

Note that the top level in the return value is an array. If your input object is expected to have exactly one property, you can just grab that element from the result (arr[0]).

The result contains nodes with two properties: a name property and either a children property or a size property.

Comments