我在D3中有一个力布局。
我有很多节点都有链接加入它们。我的问题是,如果节点符合某个标准,我想删除链接。
说我有节点A,B,C。
说这个tilda角色 - '〜'意味着连接。
If (A~B && A~C && B~C){
DELETE THE A~C link. //which would leave A~B~C
}
我已尝试浏览每个链接:
link.forEach(function{d){ ....
但我似乎无法理解我将如何做逻辑。
我会经历每个节点3次,检查是否A~B,A~C,B~C,但如果我有100个节点,那将会非常慢。
任何帮助将不胜感激:)
以下是我当前的edge / links数组的外观:
edges = [
{
"source": "A",
"target": "B",
"other information" : "randomstring",
"other information" : "randomstring"
},
{
"source": "B",
"target": "C",
"other information" : "randomstring",
"other information" : "randomstring"
} // and so on ....
]
答案 0 :(得分:2)
这是一个图论问题,我假设你想打破一个循环,这就是我要做的事情
给出尺寸g
和订单n
m
1)从links
构建哈希表,该哈希表使用链接(O(m)
,如果哈希是在恒定时间内完成)映射两个节点,例如,
// a reference to the link itself (which can be an object or a dom node)
var hash = {}
links.each(function (d) {
var u = d.source
var v = d.target
hash[u] = hash[u] || {}
// again replace this with the dom node if you want
hash[u][v] = d
})
2)运行dfs查找边缘(在an article I wrote或快速谷歌搜索中更多关于它),每当找到后边缘时,您将获得有关源/目标节点和周期长度的信息O(n + m)
3)如果周期长度为3或符合条件,则删除链接,从链接中删除O(km)
其中k
是找到的周期数
现在使用d3你可以简单地重新绑定新数据(删除一些链接)并重新渲染图形
答案 1 :(得分:1)
假设您的逻辑可以简化为检查当前entry.source是否等于以下entry.target,
你可以使用try
:
array.reduce
这可能不是最高效的解决方案,但是,检查100个对象,你应该没事; 此外,它非常合成,使用reduce。
答案 2 :(得分:1)
似乎我们有一个类似的问题,我必须创建一个函数来到达一个特定的节点。您可以在创建和使用的基本功能中看到不同版本:http://bl.ocks.org/CrandellWS/79be3b8c9e8b74549af5
最初的尝试是使用forEach
循环,但我发现使用常规for
循环更简单。虽然我希望这可以解决你的问题,你应该阅读这个answer为什么在数组迭代中使用“for ... in”这样一个坏主意?
function getObjByValue(myRoot, myType, myType2, myVal, myVal2){
var d;
console.log(typeof myRoot)
if(typeof myRoot == "object"){
for(d in myRoot){
//checking for requirements.
if(myRoot[d][myType] == myVal && myRoot[d][myType2] == myVal2 ){
console.log(d);
//accessing the specific one desired...
d3.select('#specificOne').text(myRoot[d]["other information"]);
//deleteing it from the copied array
delete myRoot[d];
//do something with the rest
printRemaining(myRoot);
//done
return;
}
}
}
}
getObjByValue(edges, 'source', 'target', 'A', 'C');
edges = [
{
"source": "A",
"target": "B",
"other information" : "randomstringAB",
"other information2" : "randomstringAB"
},{
"source": "A",
"target": "C",
"other information" : "randomstringAC",
"other information2" : "randomstringAC"
},{
"source": "B",
"target": "C",
"other information" : "randomstringBC",
"other information2" : "randomstringBC"
},{
"source": "D",
"target": "C",
"other information" : "randomstringDC",
"other information2" : "randomstringDC"
},{
"source": "C",
"target": "E",
"other information2" : "randomstringCE",
"other information" : "randomstringCE"
}
]
function getObjByValue(myRoot, myType, myType2, myVal, myVal2){
var d;
console.log(typeof myRoot)
if(typeof myRoot == "object"){
for(d in myRoot){
if(myRoot[d][myType] == myVal && myRoot[d][myType2] == myVal2 ){
console.log(d);
//accessing the specific one desired...
d3.select('#specificOne').text(myRoot[d]["other information"]);
//deleteing it from the copied array
delete myRoot[d];
printRemaining(myRoot);
console.log(d);
console.log('done');
//done
return;
}
}
}
}
function printRemaining(myArray){
for(d in myArray){
d3.select('#edges').append('p').text(myArray[d]["other information"]+'\r\n');
}
}
getObjByValue(edges, 'source', 'target', 'A', 'C');
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<p>First the specific one</p>
<div id="specificOne"></div>
<br /><br /><br /><br /><br />
<p>It's time to eat, Here is the leftovers.</p>
<div id="edges"></div>