user3209130
user3209130

Reputation: 346

how do i sum up collection based on some key using lodash

I have following Json data and i want to merge record with same customer_id, so there is single record per customer_id

  [
   {
      "id":2,
      "customer_id":2,
      "amount":50,
      "total":100,
      "currency_code":"USD",
      "customer":{
         "id":2,
         "name":"ABC Company",
         "latest_comment":null
      }
   },
   {
      "id":3,
      "customer_id":3,
      "amount":90,
      "total":60,
      "currency_code":"USD",
      "customer":{
         "id":3,
         "name":"ABC Company 1"
      }
   },
   {
      "id":7,
      "customer_id":3,
      "amount":10,
      "total":40,
      "currency_code":"USD",
      "customer":{
         "id":3,
         "name":"ABC Company 1"
      }
   }
 ]

in this sample there are two object with customer_id = 3(2nd and 3rd)

i want to sum up rows by customer_id so resulting collection looks like

   [
       {
          "id":2,
          "customer_id":2,
          "amount":50,
          "total":100,
          "currency_code":"USD",
          "customer":{
             "id":2,
             "name":"ABC Company",
             "latest_comment":null
          }
       },
       {
          "id":null,             //just because there are multiple rows with same customer_id
          "customer_id":3,
          "amount":100,
          "total":100,
          "currency_code":"USD",
          "customer":{
             "id":3,
             "name":"ABC Company 1"
          }
       }
   ]

Upvotes: 0

Views: 2907

Answers (2)

Ofisora
Ofisora

Reputation: 2737

You can use the following code to get the sum:

var arr = [{
    "id": 2,
    "customer_id": 2,
    "amount": 50,
    "total": 100,
    "currency_code": "USD",
    "customer": {
      "id": 2,
      "name": "ABC Company",
      "latest_comment": null
    }
  },
  {
    "id": 3,
    "customer_id": 3,
    "amount": 90,
    "total": 60,
    "currency_code": "USD",
    "customer": {
      "id": 3,
      "name": "ABC Company 1"
    }
  },
  {
    "id": 7,
    "customer_id": 3,
    "amount": 10,
    "total": 40,
    "currency_code": "USD",
    "customer": {
      "id": 3,
      "name": "ABC Company 1"
    }
  }
]

var output =
  _(arr)
  .groupBy('customer_id')
  .map((objs, key) => ({

    'customer_id': key,
    'amount': _.sumBy(objs, 'amount'),
    'total': _.sumBy(objs, 'total')

  }))
  .value();

console.log(output);
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.min.js"></script>

_.groupBy returns the aggregate object given the field and

_.sumBy returns the sum iterating the given field and array.

Upvotes: 1

Ori Drori
Ori Drori

Reputation: 192287

Use _.groupBy() to collect objects with the same customer_id, then merge each group to a single object using _.mergeWith().

const data = [{"id":2,"customer_id":2,"amount":50,"total":100,"currency_code":"USD","customer":{"id":2,"name":"ABC Company","latest_comment":null}},{"id":3,"customer_id":3,"amount":90,"total":60,"currency_code":"USD","customer":{"id":3,"name":"ABC Company 1"}},{"id":7,"customer_id":3,"amount":10,"total":40,"currency_code":"USD","customer":{"id":3,"name":"ABC Company 1"}}];

var result = _(data)
  // group the object by customer_id
  .groupBy('customer_id')
   // merge each group
  .map((g) => _.mergeWith({}, ...g, (o, s, k) => {
    // if the key is amount or total add the numbers
    if((k === 'amount' || k === 'total') && _.isNumber(o)) {
      return o + s;
    }
  
    // if the key is id convert it to null if there's more than one
    if(k === 'id' && _.isNumber(o) && _.isNumber(s)) {
      return null;
    }
  }))
  .value();

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

Upvotes: 1

Related Questions