How to split D3 selection into groups using selection.filter method in loop

This is my first post here, so I apologize if this seems a little awkward.

I am working on a force graph using D3.js. I am facing problems with the filter function. Here is my situation: I have created nodes in my graph that have many functions. I would first like to create subsets of all these nodes based on what the user thinks might be a suitable function and do some visual analysis.

For example, I am working on images of roses (which are my nodes) and I would like to filter them based on their roundness. The round function can go from 0 to 1000, so I tried to do 5 subsets first. The first will have nodes with roundness from 0 to 200, the second from 200 to 400, etc. Until the last subset, which will be from 800 to 1000.

To get the subsets, I use the d3.js filter function. This is where I have my problem:

Note: - var "nodes" is my set of nodes, they all exist. - var "groups = []" will contain my five node subsets. - var "thresholds = []" contains all my thresholds. ex: thresholds [0] == 0, threshold [1] == 200, threshold [2] == 400.

for(i = 0 ;  i < 5 ; i++)                       //going through the creation of 5 subsets
{
    groups[i] = nodes.filter(function(d, i)
    {   
            return d.Shape_Roundness > thresholds[i] && d.Shape_Roundness <= thresholds[i + 1];
            //Get the nodes "d" which have a roundness superior to a minimum threshold and inferior to a maximum threshold
    });
}

      

When I check the output of my subsets, there is only one result, as if the function breaks when it hits the return keyword. The larger the result is always the same in each subset and is the first node of my entire set.

But when I enter hard inputs, replacing, for example, "thresholds [i]" and "thresholds [i + 1]" with numbers 0 and 200, like this:

for(i = 0 ;  i < 5 ; i++)                       //going through the creation of 5 subsets
{
    groups[i] = nodes.filter(function(d, i)
    {   
            return d.Shape_Roundness > 0 && d.Shape_Roundness <= 200;
    });
}

      

Now I don't know why, but this works and I have of course 5 identical subsets. I thought maybe my "thresholds = []" variable doesn't contain numbers, but when I use the typeof operator for each value, the output is "numbers".

I want to use variables and not hard values ​​because I want users to be able to change thresholds. And of course not all of my nodes' functions go from 0 to 1000.

Can someone tell me what I am doing wrong?

Thank you very much, I wish you a pleasant day!

+3


source to share


1 answer


The problem is that you are using a variable i

as the loopvariable of your for-loop and as an anonymous function parameter in the filter part.

Inside the anonymous function, only the parameter is available i

, and your loop variable is invisible as it has the same name. This is called tracking variables .

As the D3 documentation explains here , the second parameter given to the function callback filter

is the index node . So inside your callback, you access thresholds[0]

for the first node from nodes

, thresholds[1]

for the second node, etc.



Since you don't need the index of the current node for your filter, the simplest solution would be to leave the parameter i

as follows:

for(i = 0 ;  i < 5 ; i++) { //going through the creation of 5 subsets 
  groups[i] = nodes.filter(function(d) { 
    return d.Shape_Roundness > thresholds[i] && d.Shape_Roundness <= thresholds[i + 1];
    //Get the nodes "d" which have a roundness superior to a minimum threshold and inferior to a maximum threshold
  });
}

      

This way the variable i

inside the callback will refer to your loop variable.

+2


source







All Articles