D3JS 在编码解码数据后工作
d3js works after encode decode data
我正在使用d3js和分层布局进行数据可视化。我的数据如下所示:
0
/ | '
/ | '
1 5 3
' | |
' | |
4 /
| /
2
由于我无法链接到多个父节点,因此我复制了显示的节点:
0
/ | '
/ | '
1 5 3
| | |
| | |
4 4 |
| | |
2 2 2
我做了一个小提琴演示来展示我的问题:
- 当我在 JSON 输入中使用正确的数据时,我有很好的布局(蓝色边框图形)。
- 当我使用循环来解析我的 JSON 输入时,我有奇怪的图形(绿色边框图形)。
这是我用来解析输入的循环:
for (i in root[2].Arcs){
var d = root[1].Nodes[root[2].Arcs[i].D];
var s = root[1].Nodes[root[2].Arcs[i].S];
if (!d.children){
d.children = [];
}
d.children.push(s);
}
对我来说:控制台中的两个打印元素是相同的,但布局的渲染不是。对象引用中可能存在一些差异。
我发现的一个糟糕的解决方案是解码然后编码我的var:
var root = JSON.parse(JSON.stringify(root));
然后脚本效果很好。但是我的根是一个很长的数组,解析需要很长时间...
有什么想法可以解释为什么我需要使用该编码/解码来显示相同的东西吗?
谢谢
你可以用这样的东西替换你的 for 循环,但不知道性能。斯菲德尔
traverse(root[1].Nodes[0]);
function traverse(node) {
for (i in root[2].Arcs) {
var d = root[1].Nodes[root[2].Arcs[i].D];
if (node.name === root[2].Arcs[i].D) {
var s = root[1].Nodes[root[2].Arcs[i].S];
var sCopy={
"name": s.name
}
traverse(sCopy);
if (!node.children) {
node.children = [];
}
node.children.push(sCopy);
}
}
}
您应该对 JSON 进行编码/解码以防止浅拷贝。要了解有关深拷贝和浅拷贝的更多信息,这里是链接。深拷贝和浅拷贝有什么区别?
如 var root = JSON.parse(JSON.stringify(root));是防止浅拷贝的错误方法,可以使用jQuery的Clone方法或简单的JavaScript切片方法来深度复制JavaScript数组。
例如。
var d=[1,2,3,4,5,6];//create array
var b=d;//copy array into another array (shallow copy/reference copy)
var e=d.slice();//clone array in another variable (deep copy)
d[0]=9; //change array element
console.log(d)// result : [9,2,3,4,5,6] (changed array)
console.log(b)// result : [9,2,3,4,5,6] (changed array due to reference)
console.log(e)// result : [1,2,3,4,5,6] (unchanged array due to deep copy)
还有另一种解决方案是使用下划线。如果你不想要下划线的完整javascript代码,那么你可以在下划线库中选择克隆部分。
在下划线中,您可以使用以下内容克隆对象数组:
var a = [{f: 1}, {f:5}, {f:10}];
var b = _.map(a, _.clone); // <----
b[1].f = 55;
console.log(JSON.stringify(a));
它将打印
[{"f":1},{"f":5},{"f":10}]
注意:性能不如原始帖子,请参阅下面的评论。这种方式是可扩展的,所以无论对象(和标志是什么样子),它都应该工作
答
这是@transcranial和@LaxmikantDange建议的"深度复制"方法的另一种看法。
我建议使用 jquery(我的首选方法:少写,多做)并使用其extend
例程:
<<load jquery>>
root = $.extend(true, {}, root[1].Nodes[0]);
graph(root2,svg);
graph(root,svg2);
确保你将true
作为第一个参数,如 http://api.jquery.com/jquery.extend/或此处所示 在 JavaScript 中深度克隆对象的最有效方法是什么?(热门答案)
不确定性能,但我希望它不会太糟糕。如果您测试,请告诉我!
也请不要说,根据您的应用程序(断开的链接等),深副本可能会有问题。例如,我最近构建了一个在图形之间共享事件的 react 应用程序 - 并且共享例如缩放事件(调整渲染对象)不会"自动共享"(因为对象是分开的,如果你明白我的意思。
当您将其他节点(即对象)推送到子节点数组上时,必须克隆(深度复制)这些对象。重新分配"="仅适用于字符串或数字数组。在将子节点推送到阵列之前对其进行深度复制可修复布局和渲染。
用于将子节点推送到数组中的原始代码:
for (i in root[2].Arcs){
var d = root[1].Nodes[root[2].Arcs[i].D];
var s = root[1].Nodes[root[2].Arcs[i].S];
if (!d.children){
d.children = [];
}
d.children.push(s);
}
改 性:
for (i in root[2].Arcs){
var d = root[1].Nodes[root[2].Arcs[i].D];
var s = root[1].Nodes[root[2].Arcs[i].S];
if (!d.children){
d.children = [];
}
d.children.push(JSON.parse(JSON.stringify(s)));
}
看看它:JSFiddle。
此外,包括群集在内的 d3 分层布局不支持开箱即用的多个父级。为此,您可以尝试使用力图布局。
- 数据属性仅在切换设备模式下工作
- OnsenUI AngularJS数据绑定无法正常工作
- 将数据输入到draggable无法工作
- 当单元格内容由于forumula从另一个工作表编译数据而更改时发送电子邮件
- 数据rel=“;背面“;无法在iPhone上工作
- Ember数据:如何;映射”;工作
- Ajax表单数据phpPOST不工作
- 我应该将哪些数据传递给 Spotify 应用程序才能使分页工作
- 数据表 + 列搜索 + 整体搜索协同工作 + 服务器端处理
- .split() 数据属性在应该工作的时候不起作用
- 与 Angular 1.5 的单向数据绑定类似于双向工作
- 数据表自动生成的序列号无法正常工作.对于每一页
- 数据表中的FixedHead没有'删除分页后无法工作
- 谷歌脚本-从网站论坛解析HTML-并将数据写入工作表
- 如何使用应用程序脚本执行API从谷歌工作表中提取数据
- 按钮上的数据加载消息无法与ajax调用一起工作
- Ember数据:DS.attr(“数字”)应该如何工作
- 使用ASP.Net MVC Web Api将JSON数据导出到Excel工作表
- 将数据传回父组件的ReactJS组件无法工作
- 数据插件选项筛选器不工作