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.
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...
See more on this question at Stackoverflow