I am trying to get a force layout up and running, and I working with some JSON that is pulled from an API that I then need to manipulate into the correct formate D3.
D3 force layout expects 2 arrays nodes
and links
. On return from the API the JSON looks like this,
[
{
"workbase" : "The House",
"service_user" : "Joe Blogs",
"service_user_id" : 100,
"role" : "Coordinator",
"staff_name" : "Jim Bean",
"staff_id" : 1
},
{
"workbase" : "The House",
"service_user" : "Joe Blogs",
"service_user_id" : 100,
"role" : "Documentation",
"staff_name" : "Jack Daniels",
"staff_id" : 2
},
{
"workbase" : "The House",
"service_user" : "Joe Blogs",
"service_user_id" : 100,
"role" : "Activities",
"staff_name" : "Morgan Spice",
"staff_id" : 3
},
{
"workbase" : "The House",
"service_user" : "Joe Blogs",
"service_user_id" : 100,
"role" : "Wellbeing",
"staff_name" : "Jonny Walker",
"staff_id" : 4
}
]
I then need split this data into user types, su
and sw
like below, and rename some attributes and add some further attributes.
var sw = [],
su = [],
links = [],
edges = [];
d3.json("test_example.json", function(error, json) {
console.log(json);
json.forEach(function(data) {
console.log(data);
sw.push({
name : data.staff_name,
id : data.staff_id,
role : data.role,
linked_to : data.service_user_id
});
if(_.findWhere(su, {name: data.service_user}) == undefined) {
su.push({ name : data.service_user, id: data.service_user_id });
}
});
var nodes = su.concat(sw);
nodes.forEach(function(data){
links.push({
target: _.findIndex(nodes, function(user) {
return user.id == data.linked_to;
}),
source: data.id
});
});
});
After this I have 2 arrays that looks like this,
Nodes
Links
For the life of my I cannot work out :
- 1: why there are 5 links there should be for and
- 2: why the first link is undefined.
Does any one have any ideas?
Ideally I should be able to loop through my nodes array, and create a links array of tragets and source, based on the node id and linked id.
1: why there are 5 links there should be four?
forEach
executes a provided function once per array element. So, if nodes
has 5 elements (as you can easily see in the very image you linked) and this function will be executed once for each element in the nodes
array, it will run 5 times.
2: why the first link is undefined?
There is no linked_to
key in the first object of nodes
array. So, you can avoid that undefined
simply checking if that key exists:
nodes.forEach(function(data){
if(data.linked_to){
links.push({
target: nodes.findIndex(function(user) {
return user.id == data.linked_to;
}),
source: data.id
});
}
});
Here, if(data.linked_to)
checks for that key.
Here is a demo:
var json = [{ "workbase": "The House", "service_user": "Joe Blogs", "service_user_id": 100, "role": "Coordinator", "staff_name": "Jim Bean", "staff_id": 1 }, { "workbase": "The House", "service_user": "Joe Blogs", "service_user_id": 100, "role": "Documentation", "staff_name": "Jack Daniels", "staff_id": 2 }, { "workbase": "The House", "service_user": "Joe Blogs", "service_user_id": 100, "role": "Activities", "staff_name": "Morgan Spice", "staff_id": 3 }, { "workbase": "The House", "service_user": "Joe Blogs", "service_user_id": 100, "role": "Wellbeing", "staff_name": "Jonny Walker", "staff_id": 4 }]; var sw = [], su = [], links = [], edges = []; json.forEach(function(data) { sw.push({ name: data.staff_name, id: data.staff_id, role: data.role, linked_to: data.service_user_id }); if (_.findWhere(su, { name: data.service_user }) == undefined) { su.push({ name: data.service_user, id: data.service_user_id }); } }); var nodes = su.concat(sw); nodes.forEach(function(data) { if (data.linked_to) { links.push({ target: nodes.findIndex(function(user) { return user.id == data.linked_to; }), source: data.id }); } }); console.log(links)
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
PS You don't need undescore.js in that forEach
. You can use Array.prototype.findIndex
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.