[英]How to check if nodes are related? How do I chose only one neighbour if it has two?
I have a force layout in D3. 我在D3中有一个部队布局。
I have many nodes with links joining them up. 我有很多带有链接的节点。 My problem is, I want to delete links if nodes meet a certain criteria.
我的问题是,如果节点满足特定条件,我想删除链接。
Say I have nodes A,B,C. 假设我有节点A,B,C。
Say this tilda character - '~' means connected. 说这个tilda字符-“〜”表示已连接。
If (A~B && A~C && B~C){
DELETE THE A~C link. //which would leave A~B~C
}
I've tried going through each link : 我试图通过每个链接:
link.forEach(function{d){ ....
but I can't seem to get my head around how I would do the logic. 但我似乎无法理解如何执行逻辑。
I would go through each node 3 times, check if A~B, A~C, B~C, but if i have 100 nodes that's going to be really slow. 我将遍历每个节点3次,检查A〜B,A〜C,B〜C,但是如果我有100个节点,那将会非常慢。
Any help would be appreciated :) 任何帮助,将不胜感激 :)
Here is how my current edges/links array looks : 这是我当前的edges / 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 ....
]
This is a graph theory problem where I assume you want to break a cycle, here's what I'd do 这是一个图论问题,我假设您想打破一个循环,这就是我要做的
Given a graph g
of size n
and order m
给定大小为
n
且阶为m
的图g
1) build a hash table out of links
which maps two nodes with a link ( O(m)
if the hash is done in constant time), eg 1)从
links
构建一个哈希表,该哈希表将两个带有链接的节点映射O(m)
如果哈希是在恒定时间内完成的,则为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) run dfs finding back edges (more about it in an article I wrote or with a quick google search), whenever you find a back edge you will have info about the source/target node and the length of the cycle O(n + m)
2)运行dfs查找后边缘(在我写的文章中或通过谷歌快速搜索找到更多关于后边缘的信息),每当找到后边缘时,您将获得有关源/目标节点和周期长度
O(n + m)
3) erase the link if the length of the cycle is 3 or whatever your criteria is, erasing from links would take O(km)
where k
is the number of cycles found 3)如果周期的长度是3或您的标准是什么,则删除链接,从链接中擦除将花费
O(km)
,其中k
是找到的周期数
Now using d3 you can simply rebind the new data (with some links removed) and rerender the graph 现在使用d3,您可以简单地重新绑定新数据(删除一些链接)并重新呈现图形
Assuming your logic could be simplified to checking if the current entry.source is equal to the following entry.target, you could use array.reduce
: 假设你的逻辑可以简化为检查当前entry.source等于以下entry.target,你可以使用
array.reduce
:
edges = [
{
"source": "A",
"target": "B",
"other information" : "randomstring",
"other information" : "randomstring"
},{
"source": "A",
"target": "C",
"other information" : "randomstring",
"other information" : "randomstring"
},{
"source": "B",
"target": "C",
"other information" : "randomstring",
"other information" : "randomstring"
},{
"source": "D",
"target": "C",
"other information" : "randomstring",
"other information" : "randomstring"
},{
"source": "C",
"target": "E",
"other information" : "randomstring",
"other information" : "randomstring"
}
]
var res = edges.reduce(function (acc, cur, i, array) {
if (array[i - 1] == undefined || acc[acc.length - 1].target == cur.source) {
acc.push(cur)
}
return acc
}, [])
console.log(res)
This is probably not the most performant solution but, checking 100 objects, you should be fine; 这可能不是最有效的解决方案,但是检查100个对象应该没问题; furthermore it's quite synthetic and an elegant use of reduce .
此外,它是完全合成的,并且还很好地使用了reduce 。
It seems that we had a similar issue that where I had to create a function to get to a specific node. 似乎我们遇到了类似的问题,即我必须创建一个函数才能到达特定节点。 You can see a different version of the same basic function where it was created and used: http://bl.ocks.org/CrandellWS/79be3b8c9e8b74549af5
您可以在创建和使用的地方看到相同基本功能的不同版本: http : //bl.ocks.org/CrandellWS/79be3b8c9e8b74549af5
The original attempts was to use forEach
looping but I found it simpler to use a regular for
loop. 最初的尝试是使用
forEach
循环,但我发现使用常规的for
循环更简单。 Though I hope this solves your problem, you should read this answer of Why is using “for…in” with array iteration such a bad idea? 尽管我希望这可以解决您的问题,但是您应该阅读以下答案 :为什么在数组迭代中使用“ 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>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.