1

I have three classes with properties (Class:Properties)

Parent: Id, Name, List

Child: Id, Name, List

SubChild: Id, Name, Value

I have a List of Parent. I want to achieve all of those subchild objects which have value (integer) >1 and <200

Edit: For better explaination So if I have List count 5 i.e. Parent1, Parent2, ..., Parent5

Each Parent instance has a list of children. so.. Parent1.Children.Count = 3, Parent2.Children.Count = 3 etc

Each Child object has 10 sub children. So Parent1.Children[0].SubChildren.Count = 10.

Each sub child has a value between 1 to 5000. And All parents have these sub children

I want to get back 5 parents back, with 3 children and only those sub children which meet the value criteria.

I tried to use following query amongst others and it doesn't work:

List<Parent> Parents = ThisParent.Where(
                        m => m.Child.Where(c => c.SubChild.Where(
                            t => t.Value > Convert.ToInt32(1)
                                 &&
                                 t.Value < Convert.ToInt32(200))));
InfoLearner
  • 14,952
  • 20
  • 76
  • 124
  • Do you want a `List` or a `List` that have matching `SubDhild`? - Yor example returns `List` not `List`. – Jon Egerton Aug 22 '11 at 08:46
  • I want List those parents which have those children, which have subchildren with the given value – InfoLearner Aug 22 '11 at 08:57
  • It sounds like `ThisParent` is an instance of `Parent`, not a `List` - you need to start with the list to filter it. – Jon Egerton Aug 22 '11 at 08:59
  • my example above doesn't compile. it was just to give an idea. ThisParent in this case is a list of parent and I want to filter those parents which have those children which have subchildren with a value within a specified range. thanks – InfoLearner Aug 22 '11 at 09:06
  • You have two answers which both look quite OK, but not accepted. This makes us think that we misunderstand your needs. Could you please provide an example of data: what you have, and what you expect to see. Using either `All` or `Any` should indeed be enough, but your formulations lack clarity, I think. – Michael Sagalovich Aug 22 '11 at 10:06
  • i think your query is right because it does make sense. i want the same as you have explained but the filter doesn't work at all... i can't seem to understand why. with "Any", i get every subchild back and filter is completely ignored. – InfoLearner Aug 22 '11 at 10:37
  • May be because the code is multithreaded? even though I have this LINQ query wrapped in a lock statement – InfoLearner Aug 22 '11 at 10:54
  • Ok, I think I know what is the problem. I might have not explained properly. Let's assume that the Parent has a collection of 5 objects. Each object has a collection of child objects in its list property. the count of child list is 3. each child object has sub child list. there are 10 sub children in each sub child list (so 5 x 3 x 10 sub children in total). each of the sub child has a value. Try your query and you'll see that all of the sub children are returned. i want the query to return ALL parents, children and THOSE subchildren which have the given value range. – InfoLearner Aug 22 '11 at 10:59
  • the reason why it returned back every parent is because all of the parents meet the criteria. i need a filtered out parent object... – InfoLearner Aug 22 '11 at 11:08

2 Answers2

0
var SubChildsValueFiltered =
    Parents.Where(P => P.Child.SelectMany(c => c.SubChild).All(sc => sc.Value > 1 && sc.Value < 200));

Change All to Any if required.

George Duckett
  • 31,770
  • 9
  • 95
  • 162
  • Cannot convert IEnumerable to IEnumerable. I need to get those parents which have those children, which have subchildren with the given value – InfoLearner Aug 22 '11 at 09:02
  • It'll return a parent if all subchild values of all children pass the test. As i say, you might need to change the `All` to `Any` depending on what you want. – George Duckett Aug 22 '11 at 09:52
  • changed to any and it returned "everything" – InfoLearner Aug 22 '11 at 09:54
  • Based on my query returning everything, and @Jon's query returning everything, i think either your data is not what you expect, or you're not describing the query you want. What i've done is give you a list of parents where the value of any subchild of any child is within the range you give. – George Duckett Aug 22 '11 at 09:56
  • I might have not explained properly. Let's assume that the Parent has a collection of 5 objects. Each object has a collection of child objects in its list property. the count of child list is 3. each child object has sub child list. there are 10 sub children in each sub child list (so 5 x 3 x 10 sub children in total). each of the sub child has a value. Try your query and you'll see that all of the sub children are returned. i want the query to return ALL parents, children and THOSE subchildren which have the given value range – InfoLearner Aug 22 '11 at 11:00
0

Updated: Have written the previous implementations into an NUnit test fixture I had handy.

The Subchild.Value of the first parent is 2, so will pass. The SubChild.Value of the second parent is 201, so will fail.

All the Asserts pass:

[TestFixture]
public class SOFixture

    public class SubChild
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public int Value { get; set; }
    }
    public class Child
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public List<SubChild> List { get; set; }
    }
    public class Parent
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public List<Child> List { get; set; }
    }

    [Test]
    public void SOTest()
    {

        var ListParent = new List<Parent>();
        ListParent.Add(
            new Parent()
            {
                ID = 1,
                Name = "1",
                List = new List<Child>() { new Child () {ID = 1, Name = "1",
                    List = new List<SubChild>() { new SubChild() {ID = 1, Name = "1", Value = 2}}
                }}
            });

        ListParent.Add(
            new Parent()
            {
                ID = 2,
                Name = "2",
                List = new List<Child>() { new Child () {ID = 2, Name = "2",
                    List = new List<SubChild>() { new SubChild() {ID = 2, Name = "2", Value = 201}}
                }}
            });
        Assert.AreEqual(2, ListParent.Count());
        Console.WriteLine(ListParent.Count());

        var FilteredParent = ListParent.Where(
                                p => p.List.Any(
                                    c => c.List.Any(sc => sc.Value > 1 && sc.Value < 200)
                                )
                            );
        Assert.AreEqual(1, FilteredParent.Count());
        Console.WriteLine(FilteredParent.Count());

        var FilteredParent2 = from lp in ListParent
                         where (
                             from c in lp.List
                             where (
                                from sc in c.List
                                where sc.Value > 1 && sc.Value < 200
                                select sc
                            ).Any()
                             select c
                        ).Any()
                         select lp;
        Assert.AreEqual(1, FilteredParent2.Count());
        Console.WriteLine(FilteredParent2.Count());
    }
)
Jon Egerton
  • 40,401
  • 11
  • 97
  • 129
  • returns all of the parents, doesn't filter – InfoLearner Aug 22 '11 at 09:49
  • I want filtered out "parent" objects which have subchildren that meet the given criteria. all of the parent objects have the sub children which have range of values so in my case, every Parent should be returned BUT only those subchildren which meet the given criteria. – InfoLearner Aug 22 '11 at 11:12