4

That title is the worst...

Anyway, what I'm trying to do is select a parent object, who contains n number of child objects. I will be passing in a list of criteria (1..n) that the child objects have to match. For the sake of brevity, here's the classes i'm working with:

public class Parent { public int Id { get; set; } public List<Child> Children { get; set; } } public class Child { public int Id { get; set; } public int ParentId { get; set; } public int SomeValue { get; set; } } 

What I'm looking for is a list of parents that contain children that match all of the SomeValues i'm passing in

So if I have:

Parent 1 Child 1, SomeValue 10 Child 2, SomeValue 20 Child 3, SomeValue 40 Parent 2 Child 4, SomeValue 10 Child 5, SomeValue 20 Child 5, SomeValue 50 

and myList is [10, 50], it needs to return Parent 2 only. If myList is [10, 20] then both parents should be returned. And finally, if myList is [10, 20, 60], nothing should be returned.

I don't think the following will work, because the values that children has that aren't in the list will remove it from the results (right?)

parents.where(p => p.children.all(c => myList.contains(c.SomeValue))); 

and an any won't work, because it will just return anything as long as one of its children matches. I need to ensure that the parent has a child that matches every item in myList. I also thought about adding a count to make sure the matched items were at least as large as the myList.length, but that might not work because SomeValue doesn't have to be distinct in the collection of children (I guess i could run a distinct subselect on the children's SomeValues?)

1
  • 1
    +1 for your comment on the title (SO won't let me quote it as it detects my comment as negative or derogatory) Commented Jan 7, 2016 at 1:15

2 Answers 2

10

You can flip your condition, and check to make sure all of the list values are contained within the Children collection:

var matches = parents.Where(p => myList.All(v => p.Children.Select(c => c.SomeValue).Contains(v))); 
Sign up to request clarification or add additional context in comments.

2 Comments

Using an Any clause instead of the .Select().Contains would be more concise: p.Children.Any(c => c.SomeValue == v)
gah! I can't believe that I didn't consider this. Thanks for the help.
0

Here's some rough code that outputs:

10,20 1 2 10,50 2 var parents = new List<Parent> { new Parent { Id = 1, Children = new List<Child> { new Child {SomeValue = 10}, new Child {SomeValue = 20}, new Child {SomeValue = 40} } }, new Parent { Id = 2, Children = new List<Child> { new Child {SomeValue = 10}, new Child {SomeValue = 20}, new Child {SomeValue = 50} } } }; var val1 = 10; var val2 = 20; var query = from a in parents from b in a.Children where b.SomeValue == val1 select a; var query2 = from a in parents from b in a.Children where b.SomeValue == val2 select a; Console.WriteLine("10,20"); foreach(var parent in query.ToList().Intersect(query2.ToList())) Console.WriteLine(parent.Id); val1 = 10; val2 = 50; Console.WriteLine("10,50"); foreach (var parent in query.ToList().Intersect(query2.ToList())) Console.WriteLine(parent.Id); 

1 Comment

A couple problems with this, mainly this won't allow for a dynamic list of search criteria without adding additional queries which will destroy performance pretty fast and also the OP is specifically asking for Fluent Linq

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.