Lambda implementation to avoid this ForEach Grandad/Dad/Child relation

I'd like to filter a list with child/subchild relation. I've tried with SelectMany/Where/Any to get this right, but the result includes list that don't match the child condition.

        var filteredGrandadList = new List<Grandad>();

        UnfilteredGrandList.ForEach(grandad =>
        {
            var filteredGrandad = new Grandad
            {
                Id = grandad.Id,
                Name = grandad.Name,
                DadList = new List<Dad>()
            };

            grandad.DadList.ForEach(dad =>
            {
                var filteredDad = new Dad
                {
                    Id = dad.Id,
                    Name = dad.Name,
                    Type = dad.Type,
                    ChildList = new List<Child>()
                };

                dad.ChildList.ForEach(child =>
                {
                    var exists =
                        child.LastName.Equals("Poe")
                    ;

                    if (exists)
                        filteredDad.ChildList.Add(child);
                });

                if (filteredDad.ChildList.Any())
                    filteredGrandad.DadList.Add(filteredDad);
            });

            if (filteredGrandad.DadList.Any())
                filteredGrandadList.Add(filteredGrandad);
        });

Any idea?.. Thanx in advance.

Jon Skeet
people
quotationmark

Well, you can do it all in a single statement:

var query = UnfilteredGrandadList.Select(grandad =>
    new Grandad
    {
        Id = grandad.Id,
        // etc
        DadList = grandad.DadList.Select(dad =>
            new Dad
            {
                Id = dad.Id,
                // etc
                ChildList = dad.ChildList
                               .Where(child => child.LastName.Equals("Poe"))
                               .ToList()
            }).Where(dad => dad.ChildList.Any()).ToList()
    }).Where(gd => gd.DadList.Any()).ToList();

So for each grandad, you build a sequence of dads, which contains a filtered list of children (filtering by last name), and then filter that sequence of dads to only contain dads with at least one child, and turn the result into a list.

You then filter the resulting grandads by ones where the dad list has at least one dad (which will by now have at least one child) - and again, turn the resulting sequence into a list.

It's not pretty, admittedly... but I'm currently unable to think of anything cleaner...

people

See more on this question at Stackoverflow