需要一种优雅的方式来映射节点和链接,为 d3.js 力图做好准备。我尝试使用 lodash 但找不到方法。我需要的是将所有嵌套对象提取到单个级别的新数组中,并且对于每个对象,根据其深层索引,生成具有源和目标属性的新链接数组...例如:如果一个对象有 2 个孩子,我需要生成 2 个链接,其中“源”是父 ID,“目标”是它本身的 ID。
这是我的输入结构:
[
{
"id": 0,
"name":"Name0",
"linkType":"PROFESSIONAL",
"children":[
{
"id": 1,
"name":"Name1",
"linkType":"FAMILY",
"children":[
{
"id": 2,
"name":"Name2",
"linkType":"FAMILY",
"children":[
{
"id": 3,
"name":"Name3",
"linkType":"FAMILY"
},
{
"id": 4,
"name":"Name4",
"linkType":"FAMILY"
}
]
},
{
"id": 5,
"name":"Name5",
"linkType":"FAMILY"
}
]
},
{
"id": 6,
"name":"Name6",
"linkType":"FAMILY"
}
]
},
{
"id": 7,
"name":"Name7",
"linkType":"PROFESSIONAL",
"children":[
{
"id": 8,
"name":"Name8",
"linkType":"FAMILY",
"children":[
{
"id": 9,
"name":"Name9",
"linkType":"FAMILY"
},
{
"id": 10,
"name":"Name10",
"linkType":"FAMILY"
}
]
},
{
"id": 11,
"name":"Name11",
"linkType":"FAMILY",
"children":[
{
"id": 12,
"name":"Name12",
"linkType":"FAMILY",
"children":[
{
"id": 13,
"name":"Name13",
"linkType":"FAMILY"
},
{
"id": 14,
"name":"Name14",
"linkType":"FAMILY"
}
]
},
{
"id": 15,
"name":"Name15",
"linkType":"FAMILY"
}
]
}
]
}
]
结果数组应该是:
const nodes = [ //no matter the deep index... all the nodes will be on the same array
{
"name":"Name0",
"linkType":"PROFESSIONAL",
},
{
"name":"Name7",
"linkType":"PROFESSIONAL",
},
{
"name":"Name1",
"linkType":"FAMILY",
}
.
.
.
]
const links = [
{
id: 0, //first generated link
source: 0 // the source node id
target: 1 // the target node id -- node Name0 is linked with node Name1
},
{
id: 1,
source: 0
target: 2
},
{
id: 2,
source: 1
target: 2
}
.
.
.
]
答案 0 :(得分:1)
您可以使用 d3.hierarchy 和 node.descendants 来获取给定根(包括该根)的所有节点。然后,您只需要获取相关数据,并为每个子项在该子项与其父项之间创建一个链接。
数组中有多个图形会添加一个层,但至少这应该提供一些想法:
var links = [];
var nodes = [];
nested.map(function(data) {
d3.hierarchy(data).descendants().forEach(function(node) {
if(node.children) node.children.forEach(function(child) {
links.push({
target: node.data.id,
source: child.data.id
})
})
nodes.push({
id: node.data.id,
name: node.data.id,
linkType: node.data.linkType
})
})
})
var nested = [
{
"id": 0,
"name":"Name0",
"linkType":"PROFESSIONAL",
"children":[
{
"id": 1,
"name":"Name1",
"linkType":"FAMILY",
"children":[
{
"id": 2,
"name":"Name2",
"linkType":"FAMILY",
"children":[
{
"id": 3,
"name":"Name3",
"linkType":"FAMILY"
},
{
"id": 4,
"name":"Name4",
"linkType":"FAMILY"
}
]
},
{
"id": 5,
"name":"Name5",
"linkType":"FAMILY"
}
]
},
{
"id": 6,
"name":"Name6",
"linkType":"FAMILY"
}
]
},
{
"id": 7,
"name":"Name7",
"linkType":"PROFESSIONAL",
"children":[
{
"id": 8,
"name":"Name8",
"linkType":"FAMILY",
"children":[
{
"id": 9,
"name":"Name9",
"linkType":"FAMILY"
},
{
"id": 10,
"name":"Name10",
"linkType":"FAMILY"
}
]
},
{
"id": 11,
"name":"Name11",
"linkType":"FAMILY",
"children":[
{
"id": 12,
"name":"Name12",
"linkType":"FAMILY",
"children":[
{
"id": 13,
"name":"Name13",
"linkType":"FAMILY"
},
{
"id": 14,
"name":"Name14",
"linkType":"FAMILY"
}
]
},
{
"id": 15,
"name":"Name15",
"linkType":"FAMILY"
}
]
}
]
}
]
var links = [];
var nodes = [];
nested.map(function(data) {
d3.hierarchy(data).descendants().forEach(function(node) {
if(node.children) node.children.forEach(function(child) {
links.push({
target: node.data.id,
source: child.data.id
})
})
nodes.push({
id: node.data.id,
name: node.data.id,
linkType: node.data.linkType
})
})
})
console.log(links,nodes);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>