Having the following classes (highly simplified):
public class Child { public string Label; public int CategoryNumber; public int StorageId; } public class Parent { public string Label; public List<Child> Children = new List<Child>(); }
And having the following data:
var parents = new List<Parent>(); var parent = new Parent() {Label="P1"}; parent.Children.Add(new Child() {Label="C1", CategoryNumber=1, StorageId=10}); parent.Children.Add(new Child() {Label="C2", CategoryNumber=2, StorageId=20}); parents.Add(parent); parent = new Parent() {Label="P2"}; parent.Children.Add(new Child() {Label="C3", CategoryNumber=1, StorageId=10}); parent.Children.Add(new Child() {Label="C4", CategoryNumber=2, StorageId=30}); parents.Add(parent); parent = new Parent() {Label="P3"}; parent.Children.Add(new Child() {Label="C5", CategoryNumber=3, StorageId=10}); parent.Children.Add(new Child() {Label="C6", CategoryNumber=2, StorageId=40}); parents.Add(parent);
Now, how would I get a list of children (with CategoryNumber=2) from the list of parents containing at least one child with CategoryNumber = 1 ?
I can do the following but it does not appear to be optimal:
var validParents = from p in parents where p.Children.Any (c => c.CategoryNumber==1) select p; var selectedChildren = validParents.Select(p => from c in p.Children where c.CategoryNumber == 2 select c);
Here's what I get for selectedChildren:
IEnumerable<IEnumerable<Child>>
IEnumerable<Child>
IEnumerable<Child>
Is it possible to only have one flat list containing the two children elements instead of two sub-list? How would it translate in LINQ ?
Select and SelectMany are projection operators. A select operator is used to select value from a collection and SelectMany operator is used to selecting values from a collection of collection i.e. nested collection.
The SelectMany in LINQ is used to project each element of a sequence to an IEnumerable<T> and then flatten the resulting sequences into one sequence. That means the SelectMany operator combines the records from a sequence of results and then converts it into one result.
The Any operator is used to check whether any element in the sequence or collection satisfy the given condition. If one or more element satisfies the given condition, then it will return true. If any element does not satisfy the given condition, then it will return false.
You can string a couple queries together, using SelectMany and Where.
var selectedChildren = (from p in parents where p.Children.Any (c => c.CategoryNumber==1) select p) .SelectMany(p => p.Children) .Where(c => c.CategoryNumber == 2); // or... var selectedChildren = parents .Where(p => p.Children.Any(c => c.CategoryNumber == 1)) .SelectMany(p => p.Children) .Where(c => c.CategoryNumber == 2);
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