如果我有这样的数据:
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 }]
我可以使用 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);
给我这个:
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 rollup 函数(但不一定必须使用 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(function(prev, cur, index, arr) {
return prev.map(function(d, i) {
return d + cur[i];
});
});
}
版本 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]
更新
如果函数必须运行,即使只有一个输入行,此方法也不适用。参见 Part II
最佳答案
一种解决方案使用 [].reduce()
和 [].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
);
}
reduce 和 map 在旧 JS 中都不是原生的,所以最好使用模块(下划线,或者可能有一个 d3 等同于 reduce
,但我没见过)。
编辑
在您的代码中使用它:
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(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13379912/