简体   繁体   English

用Lodash重复日期展平对象数组并获得唯一的键和值?

[英]Flatten an array of objects and get unique keys and values by a repeated date with Lodash?

I've been playing around with Lodash and not getting close to a solution that doesn't involve a lot of extra looping and overhead. 我一直在和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
        }
      ]
    }
  ]

I'd like to flatten this and have it combined and aggregated by using the date as the key returning some configuration like: 我想弄平它,并通过使用日期作为返回一些配置的键来组合和汇总:

[ 
  { 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 } }
]

Or even just a flat object array is fine like: 甚至只是一个平面对象数组都可以,例如:

[ 
  { date: 2019-05-15T07:00:00+0000, NameCount: 2, OtherCount: 1 },
  { date: 2019-05-16T07:00:00+0000, NameCount: 1, BuyCount: 2, SellCount: 1 }
]

Does anyone have any ideas on how to do this with either a Lodash or Vanilla solution? 有没有人对如何使用Lodash或Vanilla解决方案做到这一点有任何想法?

You can use a lodash's chain to flatten, group by the date, and then map and merge each group to a single object: 您可以使用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> 

Or you can use _.flow() to generate the function ( I'm using lodash/fp here ): 或者,您可以使用_.flow()生成函数( 我在这里使用lodash / fp ):

 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> 

Here is pure ES6 solution based on Array.reduce and Array.forEach for the object keys: 这是基于Array.reduceArray.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)) 

The main idea is to get the keys of the value object white iterating and compose an object with them while grouping by the date. 主要思想是对值对象的键进行白色迭代,并在按日期分组时用它们组成一个对象。 Then last forEach just sums each result object value. 然后last forEach只是对每个结果对象的值求和。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM