Steve K Steve K - 1 year ago 112
Javascript Question

Using Lodash, how can I transform this data to the desired format?

I'm fairly new to lodash and suspect that it can help me transform my data in the way I want. I've been reading the lodash docs but to be honest it's not sinking in, I'm not seeing the correct combination of operations I need.

Here is what I want to do:

var configs = [ {
configId: 1,
options: [ {categoryId: 1, id: 100},
{categoryId: 2, id: 200},
{categoryId: 3, id: 300} ] },
{
configId: 2,
options: [ {categoryId: 1, id: 105},
{categoryId: 2, id: 210} ] },
{
configId: 3,
options: [ {categoryId: 2, id: 200},
{categoryId: 1, id: 165},
{categoryId: 3, id: 300} ] }
];

// I want the above to look like this:
/*
[ {categoryId: 1, ids: [100, 105, 165]},
{categoryId: 2, ids: [200, 210]},
{categoryId: 3, ids: [300]} ]
*/


And here is a fiddle if you want to experiment.

When I look at the problem I think I want to:


  1. Combine all the
    configs
    objects so I have one big array of
    options
    objects

  2. Group by
    categoryId

  3. And then I really lose my way... I suspect I could use reduce() here, but then I also think I need a map() to actually produce the transformed object.



Anyway, I'm looping on this and not making progress, I'm hoping someone can point me the right direction.

Answer Source

With ES2015 Syntax:

_.map(
  _.groupBy(_.flatMap(configs, config => config.options), 'categoryId'), 
  (val, key) => ({categoryId: key, ids: _.uniq(_.map(val, v => v.id)) })
)

ES5 compatible (generated by Babel):

_.map(
  _.groupBy(
    _.flatMap(configs, function (config) {
    return config.options;
    }), 
  'categoryId'), 
  function (val, key) {
    return {
        categoryId: key,
        ids: _.uniq(_.map(val, function (v) {
            return v.id;
        }))
    };
});

Explanation:

_.flatMap(configs, config => config.options)

Takes options array from each configs object, flattens them into a single array of [{categoryId: xx, id: yy}, ...]

_.groupBy(..., 'categoryId')

Groups above array by their categoryId, as [{xx: [categoryId: xx, id: yy}, ...]

_.map(..., (val, key) => ({categoryId: key, ids: _.uniq(_.map(val, v => v.id)) }))

Receives val = [{xx: [categoryId: xx, id: yy}, ...], key: xx and maps them to object where categoryId is set to received key, and ids to array of unique ids from grouped objects. Result is the array you wanted.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download