d3嵌套在带有环的几个键上 [英] d3 nesting on several keys with a loop

查看:122
本文介绍了d3嵌套在带有环的几个键上的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用d3.nest()为了从CSV文件创建一个层次结构对象。



请帮助我理解为什么下面的代码不工作。
我没有在一个循环内使用嵌套函数,如下所述。



我有以下CSV文件,取自d3上的示例网站:

 type1,type2,type3,type4,type5,size
flare,analytics,cluster,AgglomerativeCluster,,3938
flare,analytics,cluster,CommunityStructure,
flare,analytics,cluster,MergeEdge,743
flare,analytics,graph,BetweennessCentrality 3534
flare,analytics,graph,LinkDistance,,5731

$ b b

此基本嵌套工作原理:

  data = data.entries(csv)
。 key(function(d){return d.type1;})
.key(function(d){return d.type2;})
。 })
.entries(csv);

我想使用一个值数组来指定我的键,以便动态修改它们。



这适用于:

  var data = d3.nest ; 
var nesting = [type1,type2,type3];
data = data.key(function(d){return d [nesting [0]];});
data = data.key(function(d){return d [nesting [1]];});
data = data.key(function(d){return d [nesting [2]];});
data = data.entries(csv);

但它不适用于循环...

  var data = d3.nest(); 
for(var i = 0; i {
data = data.key(function(d){return d [nesting [i]];} ;
}
data = data.entries(csv);

我不明白为什么循环版本不工作...也许我错过了一些关于d3.nest()capabilities ...



此外,我想知道如果有一个方法来跳过嵌套级别,如果没有填充级别(即:来自上面摘录的所有行上的类型5级别)。

解决方案

非常感谢您的阅读。 p>这不是 .nest()运算符的问题,它是JavaScript闭包的一个问题。任何时候都有此模式:

  for(var x = 0; x< y; x ++){
something.attachCallback(function(){
//现在用x
做一些事情});
}

你将会遇到关闭的问题。您定义的内部匿名函数不包括 x 的值的副本,它包括到外部变量的引用 x ,它会在外部变量更新时更新。因此,在循环结束时,个回调函数中的 x 的值将是 x (在上面的代码中, y ;在代码中, nesting.length )。



D3 .nest()运算符使用 .key c $ c>参数作为回调 - 直到调用 .map() .entries()。所以上面的问题适用。



有很多方法可以解决这个问题。我倾向于使用 .forEach()而不是 for 循环。这在老的浏览器中不起作用,但是大多数D3都不行,所以你可能是安全的:

  var data = d3.nest(); 
nesting.forEach(function(key){
data.key(function(d){return d [key];})
});

另一个选择是使用单独的函数进行回调定义。将迭代器变量传递给另一个函数将修复其值,因为回调现在具有对创建器函数的参数的引用,而不是原始的 x 变量: / p>

  var data = d3.nest(); 

function addKey(index){
data.key(function(d){return d [nesting [index]];})
}

for(var i = 0; i addKey(i);
}

还有其他一些方法,但在我看来 forEach 是最优雅。


I am using d3.nest() in order to make a hierarchical object from a CSV file.

Could you please help me understand why the following code does not work. I didn't manage to use the nesting function within a loop, as described below.

I have the following CSV file, taken from the examples on d3 website:

"type1","type2","type3","type4","type5","size"
"flare","analytics","cluster","AgglomerativeCluster","","3938"
"flare","analytics","cluster","CommunityStructure","","3812"
"flare","analytics","cluster","MergeEdge","","743"
"flare","analytics","graph","BetweennessCentrality","","3534"
"flare","analytics","graph","LinkDistance","","5731"

This basic nesting works:

data = data.entries(csv)
        .key(function(d) {return d.type1; })
        .key(function(d) {return d.type2; })
        .key(function(d) {return d.type3; })
        .entries(csv);

I want to use an array of values to specify my keys in order to modify them dynamically.

This works:

    var data = d3.nest();
    var nesting = ["type1","type2","type3"];
    data = data.key(function(d) {return d[nesting[0]]; });
    data = data.key(function(d) {return d[nesting[1]]; });
    data = data.key(function(d) {return d[nesting[2]]; });
    data = data.entries(csv);

But it does not work with a loop...

    var data = d3.nest();
    for(var i=0;i<nesting.length;i++)
    {
        data = data.key(function(d) {return d[nesting[i]]; });
    }
    data = data.entries(csv);

I can't understand why the loop version is not working... Maybe I miss something about the d3.nest() capabilities...

Also, I would like to know if there is a way to "skip" a nesting level if there is nothing filled at this level (ie: the "type5" level on all the lines from the extract above). How could I do that?

Thanks a lot for reading!

解决方案

This isn't a problem with the .nest() operator, it's a problem with JavaScript closures. Any time you have this pattern:

for (var x=0; x < y; x++) {
    something.attachCallback(function() {
        // now do something with x
    });
}

You are going to have problems with the closure. The inner anonymous function you're defining doesn't include a copy of the value of x, it includes a reference to the outer variable x, which will update when the outer variable updates. So by the end of your loop, the value of x in every one of your callback functions will be the final value of x in the loop (in the code above, y; in your code, nesting.length).

The D3 .nest() operator uses its .key() arguments as callbacks - they aren't executed until you call .map() or .entries(). So the problem above applies.

There are various ways to fix this; I tend to use .forEach() instead of a for loop. This doesn't work in older browsers, but neither will most of D3, so you're probably safe:

var data = d3.nest();
nesting.forEach(function(key) {
    data.key(function(d) {return d[key]; })
});

Another option is to use a separate function for callback definition. Passing the iterator variable to another function will "fix" its value, as the callback now has a reference to the argument of the creator function, not to the original x variable:

var data = d3.nest();

function addKey(index) {
    data.key(function(d) { return d[nesting[index]]; })
}

for(var i=0;i<nesting.length;i++) {
    addKey(i);
}

There are a few other approaches as well, but in my opinion forEach is the most elegant.

这篇关于d3嵌套在带有环的几个键上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆