Javascript求和数组,使用d3.nest() [英] Javascript summing arrays, using d3.nest()

查看:186
本文介绍了Javascript求和数组,使用d3.nest()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我的数据看起来像这样:

  harvest = [{type:apple,color:green ,value:1},
{type:apple,color:red,value:2},
{type:grape,color:green ,
{type:grape,color:red,value:4}]

我可以使用d3的nest.rollup()函数通过各种属性求和:

  sum_by =color 

rollup = d3.nest()。key(function(d){
return d [sum_by];
})。 b return d3.sum(d,function(g){
return g.value;
});
})。

给我这个:

  rollup = [{key:green,values:4},
{key:red,values:6}]

这正是我想要的。



然而,我的数据中的值包括数组,等长:

  harvest = [{type:apple,color:green,values:[1,2 ,3,4]},
{type:apple,color:red,values:[5,6,7,8]},
{type:grape green,values:[9,10,11,12]},
{type:grape,color:red,values:[13,14,15,16]}]

是否可以以类似的方式组合这些?例如:

  rollup = [{key:green,values:[10,12,14,16] },
{key:red,values:[18,20,22,24]}]

我觉得这可能是使用d3汇总函数(但不一定要使用d3)。



分辨率



由于@meetamit和@Superboggly的努力,我有三个解决方案:



1(因为它只使用一次reduce()和map()只使用一次):

  function sumArrays(group){
return group.reduce(function(prev,cur,index,arr){
return {
values:prev.values.map(function(d,i){
return d + cur.values [i];
})
};
});
}

版本2:

  function sumArrays(group){
return group.map(function(h){
return h.values;
})reduce (
return d + cur [i];
});
} {
return { );
}

版本3(由于数组长度可以变化,所以感兴趣):

  function sumArrays(group){
return group.reduce(function(prev,cur,index,arr){
return prev.map(function(d,i){
return d + cur.values [i];
});
},[0,0,0,0]
}

这样调用:

  function rollupArrays(){
return d3.nest()。key(function(d){
return d [sum_by];
} ).rollup(sumArrays).entries(harvest);
}

并转换为CoffeeScript:

  rollupArrays =  - > 
d3.nest()。key(d) - >
d [sum_by]
.rollup(sumArrays).entries(harvest)

sumArrays =(group) - >
group.reduce(prev,cur,index,arr) - >
values:prev.values.map(d,i) - >
d + cur.values [i]

UPDATE p>

如果函数必须运行,即使使用一个输入行,此方法也不适用。请参见第二部分

解决方案

一个解决方案使用 []。reduce() []。 map()

  // eg:sumArrays([[1,2,3,4 ],[5,6,7,8]]; //  function sumArrays(array){
return arrays.reduce(
function(memo,nums,i){
if(i == 0)
return nums.concat();
else
return memo.map(
function(memoNum,i){
return memoNum + nums [i];
}
);
},
[] // memo
);
}

reduce和map都不是原生的JS,所以最好使用模块(下划线,或者也许有一个d3相当于 reduce ,但我还没有看到它)。



strong> EDIT



在您的代码中使用它:

  sum_by =color; 

rollup = d3.nest()。key(function(d){
return d [sum_by];
})。 b var arrayToSum = d.map(function(g){return g.values;});
return sumArrays(arraysToSum)
})。


If I had data that looked like this:

harvest = [{type: "apple", color: "green", value: 1}, 
           {type: "apple", color: "red", value: 2}, 
           {type: "grape", color: "green", value: 3},
           {type: "grape", color: "red", value: 4 }]

I could sum it by various attributes using d3's nest.rollup() function:

sum_by = "color";

rollup = d3.nest().key(function(d) {
  return d[sum_by];
}).rollup(function(d) {
  return d3.sum(d, function(g) {
    return g.value;
  });
}).entries(harvest);

Giving me this:

rollup = [{key: "green", values: 4},
          {key: "red", values: 6}]

Which is just what I want.

However the values in my data consist of arrays, all of equal length:

harvest = [{type: "apple", color: "green", values: [1,2,3,4]}, 
           {type: "apple", color: "red", values: [5,6,7,8]}, 
           {type: "grape", color: "green", values: [9,10,11,12]},
           {type: "grape", color: "red", values: [13,14,15,16] }]

Is it possible to combine these in a similar way? To give for example:

rollup = [{key: "green", values: [10,12,14,16]},
          {key: "red", values: [18,20,22,24]}]

I feel this is probably possible using a d3 rollup function (but it doesn't necessarily have to be done using d3).

RESOLUTION

Thanks to the efforts of @meetamit and @Superboggly I have three solutions:

Version 1 (preferred because it uses reduce() just once and map() just once):

function sumArrays(group) {
  return group.reduce(function(prev, cur, index, arr) {
    return {
      values: prev.values.map(function(d, i) {
        return d + cur.values[i];
      })
    };
  });
}

Version 2:

function sumArrays(group) {
  return group.map(function(h) {
    return h.values;
  }).reduce(function(prev, cur, index, arr) {
    return prev.map(function(d, i) {
      return d + cur[i];
    });
  });
}

Version 3 (for interest because array length can vary):

function sumArrays(group) {
  return group.reduce(function(prev, cur, index, arr) {
    return prev.map(function(d, i) {
      return d + cur.values[i];
    });
  }, [0, 0, 0, 0]);
}

Called like this:

function rollupArrays() {
  return d3.nest().key(function(d) {
    return d[sum_by];
  }).rollup(sumArrays).entries(harvest);
}

And converted to CoffeeScript:

rollupArrays = ->
  d3.nest().key (d) ->
    d[sum_by]
  .rollup(sumArrays).entries(harvest)

sumArrays = (group) ->
  group.reduce (prev, cur, index, arr) ->
    values: prev.values.map (d,i) ->
      d + cur.values[i]

UPDATE

This method isn't suitable if the function must run, even with one input row. See Part II

解决方案

One solution uses [].reduce() and [].map():

// eg: sumArrays([ [1,2,3,4], [5,6,7,8] ]);// <- outputs [6, 8, 10, 12]
function sumArrays(arrays) {
  return arrays.reduce(
    function(memo, nums, i) {
      if(i == 0)
        return nums.concat();
      else
        return memo.map(
          function(memoNum, i) {
            return memoNum + nums[i];
          }
        );
    },
    [ ]// Start with empty Array for memo
  );
}

Both reduce and map are not native in old JS, so best use a module (underscore, or maybe there's a d3 equivalent to reduce, but I haven't seen it).

EDIT

Using it in your code:

sum_by = "color";

rollup = d3.nest().key(function(d) {
  return d[sum_by];
}).rollup(function(d) {
  var arraysToSum = d.map(function(g) { return g.values; });
  return sumArrays(arraysToSum)
}).entries(harvest);

这篇关于Javascript求和数组,使用d3.nest()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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