4

I've tried to decipher how to do this myself but my understanding of LINQ usage is pretty limited. What I have is two classes as such:

public class Grocery
{
    public string ItemName { get; set; }
    public List<ItemType> ItemTypes { get; set; }
}

public class ItemType
{
    public double Weight { get; set; }
    public long Quantity { get; set; }
}

The idea being you can have a Grocery object with ItemName "Carrots", and that comes in two different ItemTypes, e.g. where Weight = 1lb and where Weight = 2lb, with different quantities of each. Obviously there will be many more items than just carrots, and these are stored in a list also:

List<Grocery> groceries;

What I'd like to do is get a list of all quantities for all groceries, given a certain weight. E.g. I could do it like this for all items that have a 1lb type:

List<long> quantities = new List<long>();

foreach (Grocery grocery in groceries)
{
    foreach (ItemType itemType in grocery.ItemTypes)
    {
        if (itemType.Weight == 1)
        {
            quantities.Add(itemType.Quantity);
        }
    }
}

What I would like to know is how I can achieve the same result using a LINQ expression, though I'm not sure if this is possible without reverting to using .ForEach and simply doing the same as the code above but in a less verbose (and therefore less readable) way. Appreciate your help.

0

3 Answers 3

5

As Reno says, SelectMany is the way to go. But rather than using ForEach to populate a list, go LINQ all the way:

List<long> quantities = groceries.SelectMany(g => g.ItemTypes)
    .Where(t => t.Weight == 1)
    .Select(t => t.Quantity)
    .ToList();
Sign up to request clarification or add additional context in comments.

Comments

4

You can achieve this using SelectMany. In order to replicate your foreach processing, you can use the following:

List<long> quantities = groceries.SelectMany(x => x.ItemTypes)
    .Where(x => x.Weight == 1)
    .Select(x => x.Quantity)
    .ToList();

In order to get a list of quantities for each Grocery, as you mention in your question, you can use something like this:

var groceryQuantities = groceries.Select(g => new
{
    g.ItemName,
    Quantities = g.ItemTypes
        .Where(it => it.Weight == 1)
        .Select(it => it.Quantity)
        .ToList()
}).ToList();

This will create a list of anonymous objects, that looks something like this (in JSON for demonstration):

[
    {
        "ItemName": "Grocery #1",
        "Quantities": [1, 2, 3]
    },
    ...
]

You can sum the quantities, if that's what you're actually after. That would look like this:

var groceryQuantities = groceries.Select(g => new
{
    g.ItemName,
    TotalQuantity = g.ItemTypes
        .Where(it => it.Weight == 1)
        .Sum(it => it.Quantity)
}).ToList();

There's a tonne of other things you can do, but this should cover one way to approach this as a whole.

Comments

1

SelectMany is your friend:

 groceries.SelectMany(g => g.ItemTypes).Where(t => t.Weight == 1).ToList().ForEach(t => quantities.Add(t.Quantity));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.