如果我有这样(或类似)的对象:
sales = {
obs1:{
Sales1:{
Region:"North", Value: 200},
Sales2:{
Region:"South", Value:100}},
obs2:{
Sales1:{
Region:"North", Value: 50},
Sales2:{
Region:"South", Value:20}
}
}
如何按 Region
汇总属性 Value
的总和?答案可以是纯 JavaScript 或库。
最终结果应该是这样的:
totals = {North: 250, South:120}
最佳答案
正如其他人所指出的,没有内置的 JavaScript 函数可以执行此操作(有一些高阶函数,如 map
,但不足以完成任务)。但是,一些库,例如 Underscore.js提供许多实用程序来简化此类任务。
var totals = _
.chain(sales) // Wraps up the object in an "underscore object",
// so methods can be chained
// First: "flatten" the sales
.map(function(v) {
return _
.chain(v)
.map(function(v2) {
return v2;
})
.value();
})
.flatten()
// Second: group the sales by region
.groupBy('Region')
// Third: sum the groups and create the object with the totals
.map(function(g, key) {
return {
type: key,
val: _(g).reduce(function(m, x) {
return m + x.Value;
}, 0)
};
})
.value(); // Unwraps the "underscore object" back to a plain JS object
此答案假设您的数据的结构 已知 - 与其他答案相反,后者侧重于概括结构。虽然上面的代码可以通过删除硬编码的 Region
和 Value
并将嵌套级别更改为除两个以外的其他内容并将聚合函数更改为除 sum 之外的其他内容 -只要叶子包含您要分组的属性和您想要聚合的值。
function aggregate(object, toGroup, toAggregate, fn, val0) {
function deepFlatten(x) {
if ( x[toGroup] !== undefined ) // Leaf
return x;
return _.chain(x)
.map(function(v) { return deepFlatten(v); })
.flatten()
.value();
}
return _.chain(deepFlatten(object))
.groupBy(toGroup)
.map(function(g, key) {
return {
type: key,
val: _(g).reduce(function(m, x) {
return fn(m, x[toAggregate]);
}, val0 || 0)
};
})
.value();
}
它的名字是这样的:
function add(a,b) { return a + b; }
var totals = aggregate(sales, "Region", "Value", add);
另一个例子(按地区求最小值):
function min(a,b) { return a < b ? a : b; }
var mins = aggregate(sales, "Region", "Value", min, 999999);
关于javascript - 如何聚合对象属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23521894/