Search code examples
javascriptlodash

_.groupBy dynamic keys


I'm working with this data structure, and trying to produce a total object for (patApplied & insApplied) keys.

I'm confused about using _.groupBy on patApplied and insApplied when working with key names that are dynamic (they might change based on user selection).

I'm trying to groupBy map / reduce the values to match desired total object

[
  {
    procedure: '01402',
    fee: 82.08,
    patApplied: {
      'Credit Adjustment': 20,
      'User payment': 30
    },
    insApplied: {
      insPayment: 5,
      'ins check': 10
    }
  },
  {
    procedure: '01801',
    fee: 165.16,
    patApplied: {
      'Credit Adjustment': 0,
      'User payment': 10
    },
    insApplied: {
      insPayment: 0,
      'ins check': 7
    }
  }
]

desired output

let total = {
  patApplied: [ {Credit Adjustment: 20},{User payment: 40} ]
  insApplied: [ {insPayment: 10},{ins check: 7} ]
}

Solution

  • Combine the objects by spreading into _.mergeWith() and then extract the properties you want with _.pick():

    const data = [{"procedure":"01402","fee":82.08,"patApplied":{"Credit Adjustment":20,"User payment":30},"insApplied":{"insPayment":5,"ins check":10}},{"procedure":"01801","fee":165.16,"patApplied":{"Credit Adjustment":0,"User payment":10},"insApplied":{"insPayment":0,"ins check":7}}]
    
    const result = _.pick(
      _.mergeWith({}, ...data, (obj, src) => _.isNumber(obj) ? obj + src : undefined)
    , ['patApplied', 'insApplied'])
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

    And a terser version of the same solution using lodash/fp and _.flow():

    const { flow, mergeAllWith, cond, isNumber, add, pick } = _
    
    const fn = _.flow(
      mergeAllWith(cond([[isNumber, add]])),
      pick(['patApplied', 'insApplied'])
    )
    
    const data = [{"procedure":"01402","fee":82.08,"patApplied":{"Credit Adjustment":20,"User payment":30},"insApplied":{"insPayment":5,"ins check":10}},{"procedure":"01801","fee":165.16,"patApplied":{"Credit Adjustment":0,"User payment":10},"insApplied":{"insPayment":0,"ins check":7}}]
    
    const result = fn(data)
    
    console.log(result)
    <script src='https://cdn.jsdelivr.net/g/lodash@4(lodash.min.js+lodash.fp.min.js)'></script>