John Dews
John Dews

Reputation: 513

Combine Like Objects Within Array

I am working on generating tax reports based off an array of orders. Essentially I need to convert the following array:

    [
  {
    "rate": 6.75,
    "code": "US-NC-Guilford-27409",
    "grand": 39.981625,
    "tax": 2.02
  },
  {
    "rate": 7.5,
    "code": "US-NC-Orange-27516",
    "grand": 186.25,
    "tax": 11.25
  },
  {
    "rate": 7.5,
    "code": "US-NC-Orange-27516",
    "grand": 29.19625,
    "tax": 1.5
  }
]

Into separate arrays of each class "code", where the classes "codes" could equal anything, and could have any number of that type. So it would look something like this:

[  
   US-NC-Guilford-27409:[  
      {  
         "rate":6.75,
         "code":"US-NC-Guilford-27409",
         "grand":39.981625,
         "tax":2.02
      }
   ],
   US-NC-Orange-27516:[  
      {  
         "rate":7.5,
         "code":"US-NC-Orange-27516",
         "grand":186.25,
         "tax":11.25
      },
      {  
         "rate":7.5,
         "code":"US-NC-Orange-27516",
         "grand":29.19625,
         "tax":1.5
      }
   ]
]

But I'm completely open to other ways of formatting the separated data, but for when the report is generated we have to give a log of orders from each tax class.

So how would you create that output using JavaScript (Node)?

Upvotes: 2

Views: 92

Answers (2)

RobG
RobG

Reputation: 147553

There is no need for a library, Array.prototype.reduce does the job:

var data =     [
  {
    "rate": 6.75,
    "code": "US-NC-Guilford-27409",
    "grand": 39.981625,
    "tax": 2.02
  },
  {
    "rate": 7.5,
    "code": "US-NC-Orange-27516",
    "grand": 186.25,
    "tax": 11.25
  },
  {
    "rate": 7.5,
    "code": "US-NC-Orange-27516",
    "grand": 29.19625,
    "tax": 1.5
  }
]

var codes = data.reduce(function(acc, obj) {
    if (!acc.hasOwnProperty(obj.code)) acc[obj.code] = [];
    acc[obj.code].push(obj);
    return acc;
}, {});

document.write(JSON.stringify(codes));

Edit

Based on Xotic750's suggestion, the hasOwnProperty test can be simplified to:

var codes = data.reduce(function(acc, obj) {
    if (!acc[obj.code]) acc[obj.code] = [];
    acc[obj.code].push(obj);
    return acc;
}, Object.create(null));

which can be further compressed to:

var codes = data.reduce(function(acc, obj) {
      return (acc[obj.code] || (acc[obj.code] = [])) && acc[obj.code].push(obj) && acc;
}, Object.create(null));

though I wouldn't suggest that for maintainable code. If you're into ES6 arrow functions, then:

var codes = data.reduce((acc, obj) => (acc[obj.code] || (acc[obj.code] = [])) && acc[obj.code].push(obj) && acc, Object.create(null));

does the job but is seriously obfuscated.

Upvotes: 4

tato
tato

Reputation: 5569

This looks like a perfect use for lodash _.groupBy() (see doc)

var processed = _.groupBy(original, 'code');

Upvotes: -1

Related Questions