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.
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();
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With