Taraman
Taraman

Reputation: 128

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 }
                ]
            }
        ];

Upvotes: 1

Views: 4605

Answers (2)

Jeff Mercado
Jeff Mercado

Reputation: 134841

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.

Upvotes: 2

Cerbrus
Cerbrus

Reputation: 72857

This should do the trick:

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 }
];

var dest = [];
source.map(function(current){
    var id = current.DistributorId - 1;
    dest[id] = dest[id] || {
        "DistributorId": current.DistributorId,
        "DistributorName": current.DistributorName,
        "PriceLists": []
    };
    dest[id].PriceLists.push({ "Year": current.Year, "Month": current.Month });
})

Upvotes: 0

Related Questions