Complex d3.nest() manipulation

前端 未结 4 1740
清歌不尽
清歌不尽 2020-12-30 08:21

I have an array of arrays that looks like this:

var arrays = [[1,2,3,4,5],
              [1,2,6,4,5],
              [1,3,6,4,5],
              [1,2,3,6,5],
          


        
4条回答
  •  攒了一身酷
    2020-12-30 08:51

    If you extend the specification of Array, it's not actually that complex. The basic idea is to build up the tree level by level, taking each array element at a time and comparing to the previous one. This is the code (minus extensions):

    function process(prevs, i) {
      var vals = arrays.filter(function(d) { return prevs === null || d.slice(0, i).compare(prevs); })
                     .map(function(d) { return d[i]; }).getUnique();
      return vals.map(function(d) {
        var ret = { label: d }
        if(i < arrays.map(function(d) { return d.length; }).max() - 1) {
            tmp = process(prevs === null ? [d] : prevs.concat([d]), i+1);
            if(tmp.filter(function(d) { return d.label != undefined; }).length > 0)
              ret.children = tmp;
        }
        return ret;
      });
    }
    

    No guarantees that it won't break for edge cases, but it seems to work fine with your data.

    Complete jsfiddle here.

    Some more detailed explanations:

    • First, we get the arrays that are relevant for the current path. This is done by filtering out those that are not the same as prevs, which is our current (partial) path. At the start, prevs is null and nothing is filtered.
    • For these arrays, we get the values that corresponds to the current level in the tree (the ith element). Duplicates are filtered. This is done by the .map() and .getUnique().
    • For each of the values we got this way, there will be a return value. So we iterate over them (vals.map()). For each, we set the label attribute. The rest of the code determines whether there are children and gets them through a recursive call. To do this, we first check whether there are elements left in the arrays, i.e. if we are at the deepest level of the tree. If so, we make the recursive call, passing in the new prev that includes the element we are currently processing and the next level (i+1). Finally, we check the result of this recursive call for empty elements -- if there are only empty children, we don't save them. This is necessary because not all of the arrays (i.e. not all of the paths) have the same length.

提交回复
热议问题