Search code examples
c#jsonjson.net

Concatenate two list items into one item


I am trying to concatenate list items based on the productId. Apologies for the JSON naming, I know it's not the best, I'm not in control of this.

If items in my list have the same productId, I would like to concatenate them and create one item with a fees array containing the variable properties i.e. costType, feeId, feeName etc (see Desired result). When the productId is the same, the branchName, branchId, productName and bundle will all have the same value.

[{
        "branchname": "Branch",
        "branchid": "b7d79617-1c36-4be1-87b7-d7a910a5b72e",
        "productid": "d029d731-92a6-4bd3-b020-1ad282af8308",
        "productname": "Local Search",
        "bundle": false,
        "costtype": "Cost",
        "feeid": "c3d5fb93-f8be-4be2-b5b8-dd1701614e05",
        "feename": "Fee",
        "discounttype": null,
        "discountamount": null,
        "baseprice": 20,
        "grossprice": 20,
        "vatrate": 20,
        "vatamount": 4,
        "netprice": 24
    }, {
        "branchname": "Branch",
        "branchid": "b7d79617-1c36-4be1-87b7-d7a910a5b72e",
        "productid": "d029d731-92a6-4bd3-b020-1ad282af8308",
        "productname": "Local Search",
        "bundle": false,
        "costtype": "Sale",
        "feeid": "7299a1fe-fe3d-43e2-b21a-3710e1bcd720",
        "feename": "Standard Product Fee",
        "discounttype": null,
        "discountamount": null,
        "baseprice": 60,
        "grossprice": 60,
        "vatrate": 20,
        "vatamount": 12,
        "netprice": 72
    }
]

Desired result:

[{
        "branchname": "Branch",
        "branchid": "b7d79617-1c36-4be1-87b7-d7a910a5b72e",
        "productid": "d029d731-92a6-4bd3-b020-1ad282af8308",
        "productname": "Local Search",
        "bundle": false,
        "fees": [{
                "costtype": "Cost",
                "feeid": "c3d5fb93-f8be-4be2-b5b8-dd1701614e05",
                "feename": "Fee",
                "discounttype": null,
                "discountamount": null,
                "baseprice": 20,
                "grossprice": 20,
                "vatrate": 20,
                "vatamount": 4,
                "netprice": 24
            }, {
                "costtype": "Sale",
                "feeid": "7299a1fe-fe3d-43e2-b21a-3710e1bcd720",
                "feename": "Standard Product Fee",
                "discounttype": null,
                "discountamount": null,
                "baseprice": 60,
                "grossprice": 60,
                "vatrate": 20,
                "vatamount": 12,
                "netprice": 72
            }
        ]
    }
]

I have tried grouping by productId i.e. list.GroupBy(g => g.ProductId) but I'm not sure what to do next. I'm looking for an elegant LINQ solution if possible.


Solution

  • You can transform your list into the new format with this query:

    var condensed = 
        list.GroupBy(p => p.ProductId)
            .Select(g => 
            {
                var first = g.First();
                return new
                {
                    first.BranchName,
                    first.BranchId,
                    first.ProductId,
                    first.ProductName,
                    first.Bundle,
                    fees = g.Select(p => new
                    {
                        p.CostType,
                        p.FeeId,
                        p.FeeName,
                        p.DiscountType,
                        p.DiscountAmount,
                        p.BasePrice,
                        p.GrossPrice,
                        p.VatRate,
                        p.VatAmount,
                        p.NetPrice
                    })
                    .ToList()
                };
            })
            .ToList();
    

    Here is a working demo: https://dotnetfiddle.net/tweKHY