首页 > 解决方案 > 使用 Lodash 将对象数组展平并通过重复日期获取唯一键和值?

问题描述

我一直在玩 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 解决方案有任何想法吗?

标签: javascriptarrayslodash

解决方案


您可以使用 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()用来生成函数(我在这里使用 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>


推荐阅读