d3js - 力导向图:删除仅 link 自身的节点
d3js - Force-Directed Graph: Delete node that only link to itself
我正在尝试从 this example 做力导向图,但我的数据真的很大(5000 个节点)所以我想删除一些不 link 到任何其他节点的节点.
然而,在我的 JSON 中,每个节点至少有 1 个 link(即 link 到它自己)。这是我的数据示例:
{"directed": false, "graph": {},
"nodes": [{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5},
{"id": 6}, {"id": 7}, {"id": 8}, {"id": 9}, {"id": 10}, {"id": 11}, {"id": 12}],
"links": [{"source": 0, "target": 0}, {"source": 1, "target": 1},
{"source": 2, "target": 2}, {"source": 3, "target": 3},
{"source": 4, "target": 4}, {"source": 5, "target": 5},
{"source": 6, "target": 6}, {"source": 7, "target": 8},
{"source": 7, "target": 9}, {"source": 7, "target": 10},
{"source": 7, "target": 11}, {"source": 7, "target": 7},
{"source": 8, "target": 8}, {"source": 9, "target": 9},
{"source": 10, "target": 10}, {"source": 11, "target": 11},
{"source": 12, "target": 12}], "multigraph": false}
即,节点 id:0
只有 link {"source": 0, "target": 0}
,所以它应该被删除,但节点 id:7
有 links {"source": 7, "target": 8}, {"source": 7, "target": 7}
。它已 linked 到另一个节点,因此不应将其删除。
我的问题是如何删除仅 link 自身的节点?[=17=]
一种方法是首先将链接归结为不指向同一节点的链接,即 source !== target
。我选择使用 Array.prototype.reduce()
although other ways of iteration will work just the same. To speed up the elimintation of nodes later on I am also employing a Set 来存储 唯一的 id 值,不过从技术上讲,这并不是工作所必需的。
let uniqueNonSelfReferringLinks = data.links.reduce((set, {source:s, target:t}) =>
s !== t ? set.add(s).add(t) : set,
new Set()
);
过滤节点然后归结为迭代 nodes
数组查找节点 ID 值的集合:
let filteredNodes = data.nodes.filter(n => uniqueNonSelfReferringLinks.has(n.id));
将这两个步骤合并为一个可以更简洁地写成:
let filteredNodes = data.nodes.filter(
function(n) { return this.has(n.id); },
data.links.reduce((set, {source:s, target:t}) =>
s !== t ? set.add(s).add(t) : set,
new Set()
)
);
看看下面的工作演示:
var data = {
"directed": false,
"graph": {},
"nodes": [{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5},
{"id": 6}, {"id": 7}, {"id": 8}, {"id": 9}, {"id": 10}, {"id": 11}, {"id": 12}],
"links": [{"source": 0, "target": 0}, {"source": 1, "target": 1},
{"source": 2, "target": 2}, {"source": 3, "target": 3},
{"source": 4, "target": 4}, {"source": 5, "target": 5},
{"source": 6, "target": 6}, {"source": 7, "target": 8},
{"source": 7, "target": 9}, {"source": 7, "target": 10},
{"source": 7, "target": 11}, {"source": 7, "target": 7},
{"source": 8, "target": 8}, {"source": 9, "target": 9},
{"source": 10, "target": 10}, {"source": 11, "target": 11},
{"source": 12, "target": 12}],
"multigraph": false
};
let filteredNodes = data.nodes.filter(
function(n) { return this.has(n.id); },
data.links.reduce((set, {source:s, target:t}) =>
s !== t ? set.add(s).add(t) : set,
new Set()
)
);
console.log(filteredNodes);
我正在尝试从 this example 做力导向图,但我的数据真的很大(5000 个节点)所以我想删除一些不 link 到任何其他节点的节点.
然而,在我的 JSON 中,每个节点至少有 1 个 link(即 link 到它自己)。这是我的数据示例:
{"directed": false, "graph": {},
"nodes": [{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5},
{"id": 6}, {"id": 7}, {"id": 8}, {"id": 9}, {"id": 10}, {"id": 11}, {"id": 12}],
"links": [{"source": 0, "target": 0}, {"source": 1, "target": 1},
{"source": 2, "target": 2}, {"source": 3, "target": 3},
{"source": 4, "target": 4}, {"source": 5, "target": 5},
{"source": 6, "target": 6}, {"source": 7, "target": 8},
{"source": 7, "target": 9}, {"source": 7, "target": 10},
{"source": 7, "target": 11}, {"source": 7, "target": 7},
{"source": 8, "target": 8}, {"source": 9, "target": 9},
{"source": 10, "target": 10}, {"source": 11, "target": 11},
{"source": 12, "target": 12}], "multigraph": false}
即,节点 id:0
只有 link {"source": 0, "target": 0}
,所以它应该被删除,但节点 id:7
有 links {"source": 7, "target": 8}, {"source": 7, "target": 7}
。它已 linked 到另一个节点,因此不应将其删除。
我的问题是如何删除仅 link 自身的节点?[=17=]
一种方法是首先将链接归结为不指向同一节点的链接,即 source !== target
。我选择使用 Array.prototype.reduce()
although other ways of iteration will work just the same. To speed up the elimintation of nodes later on I am also employing a Set 来存储 唯一的 id 值,不过从技术上讲,这并不是工作所必需的。
let uniqueNonSelfReferringLinks = data.links.reduce((set, {source:s, target:t}) =>
s !== t ? set.add(s).add(t) : set,
new Set()
);
过滤节点然后归结为迭代 nodes
数组查找节点 ID 值的集合:
let filteredNodes = data.nodes.filter(n => uniqueNonSelfReferringLinks.has(n.id));
将这两个步骤合并为一个可以更简洁地写成:
let filteredNodes = data.nodes.filter(
function(n) { return this.has(n.id); },
data.links.reduce((set, {source:s, target:t}) =>
s !== t ? set.add(s).add(t) : set,
new Set()
)
);
看看下面的工作演示:
var data = {
"directed": false,
"graph": {},
"nodes": [{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5},
{"id": 6}, {"id": 7}, {"id": 8}, {"id": 9}, {"id": 10}, {"id": 11}, {"id": 12}],
"links": [{"source": 0, "target": 0}, {"source": 1, "target": 1},
{"source": 2, "target": 2}, {"source": 3, "target": 3},
{"source": 4, "target": 4}, {"source": 5, "target": 5},
{"source": 6, "target": 6}, {"source": 7, "target": 8},
{"source": 7, "target": 9}, {"source": 7, "target": 10},
{"source": 7, "target": 11}, {"source": 7, "target": 7},
{"source": 8, "target": 8}, {"source": 9, "target": 9},
{"source": 10, "target": 10}, {"source": 11, "target": 11},
{"source": 12, "target": 12}],
"multigraph": false
};
let filteredNodes = data.nodes.filter(
function(n) { return this.has(n.id); },
data.links.reduce((set, {source:s, target:t}) =>
s !== t ? set.add(s).add(t) : set,
new Set()
)
);
console.log(filteredNodes);