Search code examples
javascriptgroup-bylinq.js

Linq.js : Group By two properties (fields)


I have the following array:

var source = [
            { "DistributorId": 1, "DistributorName": "Distributor 01", "PriceListId": 1, "Year": 2014, "Month": 9 },
            { "DistributorId": 1, "DistributorName": "Distributor 01", "PriceListId": 2, "Year": 2014, "Month": 10 },
            { "DistributorId": 2, "DistributorName": "Distributor 02", "PriceListId": 3, "Year": 2014, "Month": 10 },
            { "DistributorId": 3, "DistributorName": "Distributor 03", "PriceListId": 4, "Year": 2014, "Month": 9 },
            { "DistributorId": 3, "DistributorName": "Distributor 03", "PriceListId": 5, "Year": 2014, "Month": 10 }
        ];

I want to to use linq.js to group these array by two fields "DistributorId" and "DistributorName" to get the following result:

var des =
        [
            {
                "DistributorId": 1,
                "DistributorName": "Distributor 01",
                "PriceLists":
                [
                    { "Year": 2014, "Month": 9 },
                    { "Year": 2014, "Month": 10 }
                ]
            },
            {
                "DistributorId": 2,
                "DistributorName": "Distributor 02",
                "PriceLists":
                [
                    { "Year": 2014, "Month": 10 }
                ]
            },
            {
                "DistributorId": 3,
                "DistributorName": "Distributor 03",
                "PriceLists":
                [
                    { "Year": 2014, "Month": 9 },
                    { "Year": 2014, "Month": 10 }
                ]
            }
        ];

Solution

  • The overload of group by that you want looks like this:

    // Overload:function(keySelector,elementSelector,resultSelector,compareSelector)
    

    First you'll need the key which is a combination of the distributor id and name. Then collect all years and months that have the same distributor id and name. The result of course and a way to compare the key objects (the properties as strings is a simple way to achieve that).

    var query = Enumerable.from(data)
        .groupBy(
            "{ Id: $.DistributorId, Name: $.DistributorName }",
            "{ Year: $.Year, Month: $.Month }",
            "{ DistributorId: $.Id, DistributorName: $.Name, PriceLists: $$.toArray() }",
            "String($.Id) + $.Name"
        )
        .toArray();
    

    Just note that I'm using the linq.js 3.x names: methods using lowerCamelCase. Change to UpperCamelCase for older versions.