我一直在和Lodash玩耍,并且没有接近一个不涉及很多额外循环和开销的解决方案。
data: [
{
name: "FirstResult", values: [
{
value: { NameCount: 1, OtherCount: 1 },
date: 2019-05-15T07:00:00+0000
},
{
value: { NameCount: 1 },
date: 2019-05-16T07:00:00+0000
}
]
},
{
name: "SecondResult",
values: [
{
value: { NameCount: 1 },
date: 2019-05-15T07:00:00+0000
},
{
value: { BuyCount: 2, SellCount: 1 },
date: 2019-05-16T07:00:00+0000
}
]
}
]
我想弄平它,并通过使用日期作为键来返回和返回一些配置,以使其合并和聚合:
[
{ date: 2019-05-15T07:00:00+0000, values: { NameCount: 2, OtherCount: 1 } },
{ date: 2019-05-16T07:00:00+0000, values: { NameCount: 1, BuyCount: 2, SellCount: 1 } }
]
或者甚至只是一个平面对象数组都可以,例如:
[
{ date: 2019-05-15T07:00:00+0000, NameCount: 2, OtherCount: 1 },
{ date: 2019-05-16T07:00:00+0000, NameCount: 1, BuyCount: 2, SellCount: 1 }
]
有人对用Lodash或Vanilla解决方案实现此方法有任何想法吗?
答案 0 :(得分:2)
您可以使用lodash链将其展平,按日期分组,然后将每个分组映射并合并到单个对象:
const fn = data => _(data)
.flatMap('values') // flatten to array of objects
.groupBy(o => o.date.toISOString()) // group by the iso representation
.map(group => { // map the groups by merging, and converting to require format
const { date, value } = _.mergeWith({}, ...group, (objValue, srcValue) =>
_.isNumber(objValue) ? objValue + srcValue : undefined // combine numeric values
)
return {
date,
...value,
}
})
.value()
const data = [{"name":"FirstResult","values":[{"value":{"NameCount":1,"OtherCount":1},"date": new Date("2019-05-15T07:00:00.000Z")},{"value":{"NameCount":1},"date": new Date("2019-05-16T07:00:00.000Z")}]},{"name":"SecondResult","values":[{"value":{"NameCount":1},"date":new Date("2019-05-15T07:00:00.000Z")},{"value":{"BuyCount":2,"SellCount":1},"date": new Date("2019-05-16T07:00:00.000Z")}]}]
const result = fn(data)
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
或者您可以使用_.flow()
生成函数(I'm using lodash/fp here):
const { flow, flatMap, groupBy, map, mergeAllWith, cond, isNumber, add } = _
const fn = flow(
flatMap('values'), // flatten to array of objects
groupBy(o => o.date.toISOString()), // group by the iso representation
map(mergeAllWith(cond([[isNumber, add]]))), // combine numeric values
map(({ date, value }) => ({ date, ...value })) // format the objects
)
const data = [{"name":"FirstResult","values":[{"value":{"NameCount":1,"OtherCount":1},"date": new Date("2019-05-15T07:00:00.000Z")},{"value":{"NameCount":1},"date": new Date("2019-05-16T07:00:00.000Z")}]},{"name":"SecondResult","values":[{"value":{"NameCount":1},"date":new Date("2019-05-15T07:00:00.000Z")},{"value":{"BuyCount":2,"SellCount":1},"date": new Date("2019-05-16T07:00:00.000Z")}]}]
const result = fn(data)
console.log(result)
<script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>
答案 1 :(得分:0)
这是基于Array.reduce和Array.forEach作为对象键的纯 ES6 解决方案:
const data = [{"name":"FirstResult","values":[{"value":{"NameCount":1,"OtherCount":1},"date": new Date("2019-05-15T07:00:00.000Z")},{"value":{"NameCount":1},"date": new Date("2019-05-16T07:00:00.000Z")}]},{"name":"SecondResult","values":[{"value":{"NameCount":1},"date":new Date("2019-05-15T07:00:00.000Z")},{"value":{"BuyCount":2,"SellCount":1},"date": new Date("2019-05-16T07:00:00.000Z")}]}]
let result = data.reduce((r, { values }) => {
values.forEach(({ value, date }) => {
let keys = Object.keys(value), d = date.toISOString()
r[d] = r[d] || Object.assign({}, ...keys.map(x => ({ date: d, [x]: 0 })))
keys.forEach(k => r[d][k] = (r[d][k] || 0) + value[k])
})
return r
}, {})
console.log(Object.values(result))
主要思想是对值对象的键进行白色迭代,并在按日期分组时用它们组成对象。然后最后forEach
只对每个结果对象值求和。