Search code examples
javascriptangularlodashangular2-services

lodash Groupby based on multiple conditions


i am using angular 4 for one of my projects and i have a situation where i have to group the data based on multiple conditions as explained below.

Raw data

[
{
    age: "12",
    details: [
        {
            address: "street1"
        }
    ]
},
{
    age: "12",
    details: [
        {
            address: "street2"
        }
    ]
},
{
    age: "12",
    details: [
        {
            address: "street1"
        }
    ]
}]

I want to group data based on both age and address field so the result would be something like

{
 stree1: [{
        age: "12",
        details: [
            {
                address: "street1"
            }
        ]
    }, {
        age: "12",
        details: [
            {
                address: "street1"
            }
        ]
    }

    ],
        street2: [{
            age: "12",
            details: [
                {
                    address: "street1"
                }
            ]
        }]
    }

I know we can use lodash to group the data based on single condition like

_.groupBy(data, 'age');

But i am not understanding how to do this based on multiple conditions. I want to group all those objects which has same address and same age. Something like

_.groupBy(data, 'age' && details[0].address);

How to go about this. Please help.


Solution

  • If you are sure that your object structure will be exactly the same always and will have only one object in details then you can directly do Stringify to identify the combo, if your object have several data, then you can create a new object {age: value, street: value} and stringify it to identify the combo. However I will strongly suggest not to use any pipe or anything as deliminator, and joining them to create unique combination of string to find a group. Sometimes that can spoil your value.

    Here is what you need:

    _(rawData).groupBy(JSON.stringify).filter(arr=>arr.length>1).mapKeys(v=>v[0].details[0].address).value()

    Here is an working example:

    var rawData = [
    {
        age: "12",
        details: [
            {
                address: "street1"
            }
        ]
    },
    {
        age: "12",
        details: [
            {
                address: "street2"
            }
        ]
    },
    {
        age: "12",
        details: [
            {
                address: "street1"
            }
        ]
    }];
    
    var result = _(rawData)
                    .groupBy(JSON.stringify)
                    .filter(arr=>arr.length>1)
                    .mapKeys(v=>v[0].details[0].address)
                    .value();
                    
    console.log('Expected result: ', result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>

    Here is what you do if there can be multiple other things in your object

    var rawData = [
    {
        age: "12",
        details: [
            {
                address: "street1"
            }
        ]
    },
    {
        age: "12",
        details: [
            {
                address: "street2"
            }
        ]
    },
    {
        age: "12",
        details: [
            {
                address: "street1"
            }
        ]
    }];
    
    var result = _(rawData)
                    .groupBy(obj=>JSON.stringify({age: obj.age, address: obj.details[0].address}))
                    .filter(arr=>arr.length>1)
                    .mapKeys(v=>v[0].details[0].address)
                    .value();
                    
    console.log('Expected result: ', result);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>