Javascript求和数组,使用d3.nest()

Javascript求和数组,使用d3.nest(),javascript,d3.js,Javascript,D3.js,如果我有这样的数据: 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 }] function rollupArrays()

如果我有这样的数据:

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 }]
function rollupArrays() {
  return d3.nest().key(function(d) {
    return d[sum_by];
  }).rollup(sumArrays).entries(harvest);
}
我可以使用d3的nest.rollup()函数按各种属性求和:

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);
var rollup = d3.nest().key(function(d) {
  return d[sum_by];
}).rollup(function(d) {
    var result = d.reduce(function(prev, cur, index, arr) {
        return prev.values.map(function(d,i) { return d + cur.values[i];});
    });

    return result;
}).entries(harvest);
给我这个:

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", color: "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()
仅使用一次):

第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];
    });
  });
}
版本3(出于兴趣,因为数组长度可能不同):

这样称呼:

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 }]
function rollupArrays() {
  return d3.nest().key(function(d) {
    return d[sum_by];
  }).rollup(sumArrays).entries(harvest);
}
并转换为咖啡脚本:

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]
更新


如果函数必须运行,即使只有一个输入行,此方法也不适用。请参阅一个解决方案使用
[].reduce()
[].map()


@meetamit我喜欢你使用reduce的想法

如果您只想使用d3解决此问题,它还有一个内置的reduce,您可以将其与nest函数结合使用:

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);
var rollup = d3.nest().key(function(d) {
  return d[sum_by];
}).rollup(function(d) {
    var result = d.reduce(function(prev, cur, index, arr) {
        return prev.values.map(function(d,i) { return d + cur.values[i];});
    });

    return result;
}).entries(harvest);

如果您愿意,您可以使用它。

此解决方案利用和的新功能:

var输入=[
{类型:“苹果”,颜色:“绿色”,值:[1,2,3,4]},
{类型:“苹果”,颜色:“红色”,值:[5,6,7,8]},
{类型:“葡萄”,颜色:“绿色”,值:[9,10,11,12]},
{类型:“葡萄”,颜色:“红色”,值:[13,14,15,16]}
];
var汇总=d3.汇总(
输入,
vs=>d3.transpose(vs.map(d=>d.values)).map(vs=>d3.sum(vs)),
d=>d.color
);
var output=rolled_up.map(([color,values])=>({key:color,values:values}));
控制台日志(输出)

谢谢。这个函数可以工作,但我还没有弄清楚如何应用它。简单地说“return summarrays(d,function(g){return g.values;…”是不起作用的,给出“memo.map不是一个函数”。任何指针都值得赞赏。太好了。我花了一点时间来解决这个问题,但现在工作很好。很酷,谢谢。但是你可能应该使用@Superboggly的解决方案,因为它更紧凑(仍然使用相同的
reduce()
方法)。好的。这两种解决方案都很好,因为我可以把它们带到各个方面,真正了解这些方法。谢谢!meetamit,基于reduce()的观点在没有初始值的情况下工作您对我上面编辑中的版本感觉如何?根据我目前的测试,它似乎可以工作。实际上,它仍然使用本机的
reduce()
,但比我的版本紧凑得多。我没有意识到reduce可以在没有初始值的情况下工作(在这种情况下,它从第二个元素开始,传递第一个val)。酷。我恐怕这里有一个bug。当我用现有类型或颜色(例如,第三行表示“apple”之类)向数据中添加另一行时,我得到消息“prev.values未定义”。有什么建议吗?@DerekHill,我想通过添加
{values:…}
(很难解释原因,你需要考虑一下)。解决方案有点不确定。啊,是的!这对我的解决方案不是很好!基本上,我正在更改prev的类型,因为它正在运行-您不会注意到只有两个项目需要迭代。meetamit的修复方法很好!为了提供另一种替代方法,您还可以将初始化值传递给reduce方法。请检查