开发者

LINQ suming nested groups in one statement

I am converting some code to LINQ, at the same time exploring to what extent LINQ can accomplish.

Can the following code be condensed into a single LINQ query or method?

Dictionary<string, ItemPack> consolidated = new Dictionary<string, ItemPack>();
foreach (var product in Products)
{
    foreach (var smallpack in product.ItemPacks)
    {
        ItemPack bigpack;
        if (consolidated.TryGetValue(smallpack.ItemCode, out bigpack))
        {
            // the big pack quantity += quantity for making one product * the number of that product
            bigpack.Quantity += smallpack.Quantity * product.Quantity;

            // References: we make sure that the small pack is using the Item in the big pack.
            // otherwise there will be 2 occurance of the same Item
            smallpack.Item = bigpack.Item;
        }
        else
        {
            bigpack = new ItemPack(smallpack); // Copy constructor
            bigpack.Quantity = smallpack.Quantity * product.Quantity;
            consolidated.Add(smallpack.ItemCode, bigpack);
        }
    }
}
return c开发者_StackOverflowonsolidated;

In English, each product is made up of several items of different quantities. These items are grouped by item code and are packs into smallpacks. These smallpacks are shipped together as a unit product. There are many different products. A single item can be used in different product.

I now have a list of products and the quantity required for each for shipment. I want a LINQ statement to consolidate a flat list of items and their quantities.

I have gotten this far, but it looks like it does not work:

var packsQuery = from product in Products
                 from smallpack in product.ItemPacks
                 select new {Item = smallpack.Item, Quantity = smallpack.Quantity * product.Quantity};

foreach (var pack in packsQuery)
{
    consolidated.Add(pack.Item.ItemCode, new ItemPack(pack.Item, pack.Quantity));
}

If I group first, then I cannot select item for its quantity. If I select first, then I lose the grouping. Chicken and egg story?

EDIT: Useful note: smallpack is of type ItemPack which looks like this

public class ItemPack
{
     Item { get; } // The item in this pack, which *must* be a shared reference across all objects that uses this Item. So that change in Item properties are updated everywhere it is used. e.g. Price.
     ItemCode { get; } // The item code
     Quantity { get; } // The number of such Item in this pack.
}


    var query = (from product in Products
                from smallPack in product.ItemPacks
                select new
                {
                    ItemCode = smallPack.ItemCode,
                    Item = smallPack.Item,
                    Quantity = smallPack.Quantity * product.Quantity,
                })
                .GroupBy(p => p.ItemCode)
                .Select(p => new
                {
                    ItemCode = p.Key,
                    Item = p.FirstOrDefault(),
                    Quantity = p.Sum(x=>x.Quantity)
                })
                .ToDictionary(p=>p.ItemCode);


Thanks for putting me in the right direction. I managed to work out the full query syntax version:

var query = from product in Products
            from smallpack in product.ItemPacks
            select new {
                Item = smallpack.Item,
                Quantity = smallpack.Quantity * product.Quantity
            } into mediumpack
            group mediumpack by mediumpack.Item.ItemCode into bigpack
            select new {
                Item = bigpack.First().Item, // shared reference
                Quantity = bigpack.Sum(a => a.Quantity);
            }

query.ToDictionary(...);

Any comments as to whether this is fine?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜