6

Let's say I have the following classes:

class Parent
{
    bool Gender { get; set; }
    List<Child> Children { get; set; }
}


class Child
{
    bool Gender { get; set; }
    List<Child> GrandChildren { get; set; }
}


class GrandChild
{
    bool Gender { get; set; }
}

Using linq, can anyone help me filter a Parent object by returning a List<Child> where each Child has Gender == false and each Child's GrandChild has Gender == false?

I've managed to return a List<GrandChild> but I really need the hierarchy to be maintained.

pedrodbsa
  • 1,361
  • 3
  • 10
  • 12
  • 2
    Do you mean you *only* want the children to be returned where their gender is false and all their children have a gender of false? – Jon Skeet Dec 27 '10 at 17:39
  • 1
    As a side note, I'd suggest you to change `Gender` property to Enum {Male,Female} because `Gender=true/false` is pretty unclear to understand... – digEmAll Dec 27 '10 at 17:42
  • 3
    I love Gender being a bool. So is male represented by `true` and female by `false`? Like in real life? ;-P – Klaus Byskov Pedersen Dec 27 '10 at 17:43
  • :) Gender was just an example.. thanks for all the quick answers – pedrodbsa Dec 27 '10 at 17:52
  • Maybe i wasn't clear enough.. The queries do not filter the grandchildren.. they only return a list that have Gender==false GrandChild objects. But the GrandChildren collection still isn't filtered.. it still returns Gender == false and true GranChild – pedrodbsa Dec 27 '10 at 17:59

4 Answers4

17

You're looking for

.Where(p => p.Children.All(c => !c.Gender && c.GrandChildren.All(g => !g.Gender))
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
7

Your question is a bit vague. Here's a solution which rebuilds the children and grandchildren lists, I wasn't sure if I needed the child.GrandChildren.All(gc => !gc.Gender) so I left it out for clarity:

parents.Select(parent => new Parent
{
  Gender = parent.Gender,
  Children = parent.Children.Where(child => !child.Gender).Select(child => new Child
    {
      Gender = false,
      GrandChildren = child.GrandChildren.Where(gc => !gc.Gender).ToList()
    }
  ).ToList()
})
fejesjoco
  • 11,763
  • 3
  • 35
  • 65
3
  • help me filter a Parent object
  • by returning a List<Child>
  • where each Child has Gender == false
  • and each Child's GrandChild has Gender == false?

Translated literally:

List<Child> results =
(
  from c in theParent.Children
  where !c.Gender
  where c.GrandChildren.Any(gc => !gc.Gender)
  select c
).ToList()

Based on your comments, what you really want:

List<Parent> result = 
(
from p in Parents
where !p.Gender
select new Parent()
{
  Gender = p.Gender,
  Children = 
  (
    from c in p.Children
    where !c.Gender
    select new Child()
    {
      Gender = c.Gender,
      GrandChildren =
      (
        from gc in c.GrandChildren
        where !gc.Gender
        select new GrandChild()
        {
          Gender = gc.Gender
        }
      ).ToList()
    }
  ).ToList()
}).ToList();
Amy B
  • 108,202
  • 21
  • 135
  • 185
1
var filteredParents = 
    from p in parents
    where p.Children.All(child => !child.Gender &&
                         child.GrandChildren.All(grandChild => !grandChild.Gender))
    select p;

Using All method here ensures that the predicate passed as an argument to that method is true for all elements in given sequence.

Given code checks for each parent that has All children with (Gender = false and also having All grand children Gender = false).

decyclone
  • 30,394
  • 6
  • 63
  • 80