javascript 减少数组中对象的多个键
javascript reduce over multiple keys of objects in an array
我有以下类型的对象映射(下面的示例数据)
{[date:string]:Array<{[type:string]:{amount:number, price:number}}>}
并且我需要将数组缩减为单个对象的金额总和和平均价格
我已经阅读了一些关于如何减少像
这样的对象的数据的post
Javascript reduce on array of objects
在我的例子中,"type" 是 ["PV"、"BHKW"、"FALLBACK"] 的 ENUM,但它可以扩展。除了在循环中编写声明外,我不知道如何使用 array.reduce 来更优雅地完成此操作。
有什么建议吗?
{
"2018-08-01T11:00:00+02:00": [
{
"BHKW": {
"amount": 131,
"price": 85
},
"FALLBACK": {
"amount": 84,
"price": 1
}
},
{
"BHKW": {
"amount": 307,
"price": 58
},
"PV": {
"amount": 4,
"price": 60
}
}
],
"2018-08-01T12:00:00+02:00": [
{
"BHKW": {
"amount": 288,
"price": 59
},
"PV": {
"amount": 742,
"price": 73
}
},
{
"BHKW": {
"amount": 250,
"price": 49
},
"PV": {
"amount": 507,
"price": 98
}
},
{
"PV": {
"amount": 368,
"price": 22
},
"BHKW": {
"amount": 357,
"price": 73
}
},
{
"FALLBACK": {
"amount": 135,
"price": 62
},
"BHKW": {
"amount": 129,
"price": 93
}
}
],
解决了!
var x = _.reduce(
list,
(acc, item) => {
for (const key in item) {
if (!acc[key]) {
acc[key] = { price: 0, amount: 0 };
}
if (item[key] && item[key].price) {
acc[key].price += item[key].price;
}
if (item[key] && item[key].amount) {
acc[key].amount += item[key].amount;
}
}
return acc;
},
{}
);
您可以将 lodash#mapValues
to transform each value of the object data
object. To combine all objects with the same key values, you can use lodash#mergeWith
与回调测试结合使用,以评估正在转换的键是否会被评估。
const result = _.mapValues(data, collection =>
_.mergeWith({}, ...collection, (a = 0, b = 0, key) =>
['amount', 'price'].includes(key)
? a + b
: void 0 // is equivalent to undefined to retain current value
));
const data = {
"2018-08-01T11:00:00+02:00": [
{
"BHKW": {
"amount": 131,
"price": 85
},
"FALLBACK": {
"amount": 84,
"price": 1
}
},
{
"BHKW": {
"amount": 307,
"price": 58
},
"PV": {
"amount": 4,
"price": 60
}
}
],
"2018-08-01T12:00:00+02:00": [
{
"BHKW": {
"amount": 288,
"price": 59
},
"PV": {
"amount": 742,
"price": 73
}
},
{
"BHKW": {
"amount": 250,
"price": 49
},
"PV": {
"amount": 507,
"price": 98
}
},
{
"PV": {
"amount": 368,
"price": 22
},
"BHKW": {
"amount": 357,
"price": 73
}
},
{
"FALLBACK": {
"amount": 135,
"price": 62
},
"BHKW": {
"amount": 129,
"price": 93
}
}
]
};
const result = _.mapValues(data, collection =>
_.mergeWith({}, ...collection, (a = 0, b = 0, key) =>
['amount', 'price'].includes(key)
? a + b
: void 0 // is equivalent to undefined to retain current value
));
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
另一种方法(虽然不像已经发布的 _.merge
方法那么优雅)是 _.mapValues/_.reduce/_.assignWith or _.extendWith
:
var data = { "2018-08-01T11:00:00+02:00": [{ "BHKW": { "amount": 131, "price": 85 }, "FALLBACK": { "amount": 84, "price": 1 } }, { "BHKW": { "amount": 307, "price": 58 }, "PV": { "amount": 4, "price": 60 } } ], "2018-08-01T12:00:00+02:00": [{ "BHKW": { "amount": 288, "price": 59 }, "PV": { "amount": 742, "price": 73 } }, { "BHKW": { "amount": 250, "price": 49 }, "PV": { "amount": 507, "price": 98 } }, { "PV": { "amount": 368, "price": 22 }, "BHKW": { "amount": 357, "price": 73 } }, { "FALLBACK": { "amount": 135, "price": 62 }, "BHKW": { "amount": 129, "price": 93 } } ] }
var result =
_.mapValues(data, (x) =>
_.reduce(x, (r, c) =>
_.assignWith(r, c, (o, s) =>
o && s ? ({ amount: o.amount + s.amount, price: o.price + s.price }) : {...o, ...s})
)
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
我有以下类型的对象映射(下面的示例数据)
{[date:string]:Array<{[type:string]:{amount:number, price:number}}>}
并且我需要将数组缩减为单个对象的金额总和和平均价格
我已经阅读了一些关于如何减少像
这样的对象的数据的postJavascript reduce on array of objects
在我的例子中,"type" 是 ["PV"、"BHKW"、"FALLBACK"] 的 ENUM,但它可以扩展。除了在循环中编写声明外,我不知道如何使用 array.reduce 来更优雅地完成此操作。
有什么建议吗?
{
"2018-08-01T11:00:00+02:00": [
{
"BHKW": {
"amount": 131,
"price": 85
},
"FALLBACK": {
"amount": 84,
"price": 1
}
},
{
"BHKW": {
"amount": 307,
"price": 58
},
"PV": {
"amount": 4,
"price": 60
}
}
],
"2018-08-01T12:00:00+02:00": [
{
"BHKW": {
"amount": 288,
"price": 59
},
"PV": {
"amount": 742,
"price": 73
}
},
{
"BHKW": {
"amount": 250,
"price": 49
},
"PV": {
"amount": 507,
"price": 98
}
},
{
"PV": {
"amount": 368,
"price": 22
},
"BHKW": {
"amount": 357,
"price": 73
}
},
{
"FALLBACK": {
"amount": 135,
"price": 62
},
"BHKW": {
"amount": 129,
"price": 93
}
}
],
解决了!
var x = _.reduce(
list,
(acc, item) => {
for (const key in item) {
if (!acc[key]) {
acc[key] = { price: 0, amount: 0 };
}
if (item[key] && item[key].price) {
acc[key].price += item[key].price;
}
if (item[key] && item[key].amount) {
acc[key].amount += item[key].amount;
}
}
return acc;
},
{}
);
您可以将 lodash#mapValues
to transform each value of the object data
object. To combine all objects with the same key values, you can use lodash#mergeWith
与回调测试结合使用,以评估正在转换的键是否会被评估。
const result = _.mapValues(data, collection =>
_.mergeWith({}, ...collection, (a = 0, b = 0, key) =>
['amount', 'price'].includes(key)
? a + b
: void 0 // is equivalent to undefined to retain current value
));
const data = {
"2018-08-01T11:00:00+02:00": [
{
"BHKW": {
"amount": 131,
"price": 85
},
"FALLBACK": {
"amount": 84,
"price": 1
}
},
{
"BHKW": {
"amount": 307,
"price": 58
},
"PV": {
"amount": 4,
"price": 60
}
}
],
"2018-08-01T12:00:00+02:00": [
{
"BHKW": {
"amount": 288,
"price": 59
},
"PV": {
"amount": 742,
"price": 73
}
},
{
"BHKW": {
"amount": 250,
"price": 49
},
"PV": {
"amount": 507,
"price": 98
}
},
{
"PV": {
"amount": 368,
"price": 22
},
"BHKW": {
"amount": 357,
"price": 73
}
},
{
"FALLBACK": {
"amount": 135,
"price": 62
},
"BHKW": {
"amount": 129,
"price": 93
}
}
]
};
const result = _.mapValues(data, collection =>
_.mergeWith({}, ...collection, (a = 0, b = 0, key) =>
['amount', 'price'].includes(key)
? a + b
: void 0 // is equivalent to undefined to retain current value
));
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
另一种方法(虽然不像已经发布的 _.merge
方法那么优雅)是 _.mapValues/_.reduce/_.assignWith or _.extendWith
:
var data = { "2018-08-01T11:00:00+02:00": [{ "BHKW": { "amount": 131, "price": 85 }, "FALLBACK": { "amount": 84, "price": 1 } }, { "BHKW": { "amount": 307, "price": 58 }, "PV": { "amount": 4, "price": 60 } } ], "2018-08-01T12:00:00+02:00": [{ "BHKW": { "amount": 288, "price": 59 }, "PV": { "amount": 742, "price": 73 } }, { "BHKW": { "amount": 250, "price": 49 }, "PV": { "amount": 507, "price": 98 } }, { "PV": { "amount": 368, "price": 22 }, "BHKW": { "amount": 357, "price": 73 } }, { "FALLBACK": { "amount": 135, "price": 62 }, "BHKW": { "amount": 129, "price": 93 } } ] }
var result =
_.mapValues(data, (x) =>
_.reduce(x, (r, c) =>
_.assignWith(r, c, (o, s) =>
o && s ? ({ amount: o.amount + s.amount, price: o.price + s.price }) : {...o, ...s})
)
)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>