如何检查节点是否相关?如果它有两个邻居,我如何只选择一个

How to check if nodes are related? How do I chose only one neighbour if it has two?

本文关键字:邻居 两个 选择 一个 如果 节点 检查 何检查 是否      更新时间:2023-09-26

我在D3中有一个强制布局。

我有许多节点,链接将它们连接起来。我的问题是,如果节点满足一定的条件,我想删除链接。

假设我有节点A B C。

说这个大字符- '~'表示连接。

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个节点,这将是非常慢的。

任何帮助都将是感激的:)

这是我当前的边/链接数组的样子:

edges = [
{
    "source": "A",
    "target": "B",
    "other information" : "randomstring",
    "other information" : "randomstring"
},
{
    "source": "B",
    "target": "C",
    "other information" : "randomstring",
    "other information" : "randomstring"
} // and so on ....
]

这是一个图论问题,我假设你想打破一个循环,我会这样做

给定一个大小为n阶为m的图g

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查找后缘(在我写的一篇文章中有更多关于它的内容,或者在谷歌上快速搜索一下),每当您找到后缘时,您将获得有关源/目标节点和周期长度的信息O(n + m)

3)如果循环长度为3或无论你的标准是什么,从链接中删除将使用O(km),其中k是找到的循环数

现在使用d3,您可以简单地重新绑定新数据(删除一些链接)并渲染图形

假设您的逻辑可以简化为检查当前条目是否。Source等于下面的条目。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)

小提琴

这可能不是性能最好的解决方案,但是,检查100个对象,你应该没问题;此外,它是非常综合的,并且是reduce的一个优雅的使用。

似乎我们遇到了一个类似的问题,我必须创建一个函数才能到达特定的节点。您可以看到创建和使用相同基本函数的不同版本:http://bl.ocks.org/CrandellWS/79be3b8c9e8b74549af5

最初的尝试是使用forEach循环,但我发现使用常规for循环更简单。虽然我希望这能解决您的问题,但您应该阅读为什么在数组迭代中使用"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>