Reputation: 131
Given the Objects :
class Parent
{
private int id;
public int Id
{
get { return id; }
set { id = value; }
}
private List<Child> childrenList;
public List<Child> ChildrenList
{
get { return childrenList; }
set { childrenList = value; }
}
}
class Child
{
private int idSub;
public int IdSub
{
get { return idSub; }
set { idSub = value; }
}
private bool isST;
public bool IsST
{
get { return isST; }
set { isST = value; }
}
}
I have a List<Parent> parentList = new List<Parent>()
and inside Parent
object there is a list of Child
which is called ChildrenList.
Child
has a property IsST
.
I want to return only the Child
which has the property IsST
equals true and if the Parent
doesn't satisfy the condition, doesn't need to be returned.
And both lists returned, need to be typed with its respectively types.
What I have so far:
List<Parent> parentList = new List<Parent>()
{
new Parent()
{
Id = 1,
ChildrenList = new List<Child>()
{
new Child()
{
IdSub = 1,
IsST = true
},
new Child()
{
IdSub = 2,
IsST = true
}
}
},
new Parent()
{
Id = 2,
ChildrenList = new List<Child>()
{
new Child()
{
IdSub = 3,
IsST = false
},
new Child()
{
IdSub = 4,
IsST = true
}
}
},
new Parent()
{
Id = 3,
ChildrenList = new List<Child>()
{
new Child()
{
IdSub = 5,
IsST = false
},
new Child()
{
IdSub = 6,
IsST = false
}
}
}
};
var parentFilteredList = parentList
.Select(c => c.ChildrenList
.Where(d => d.IsST)
.ToList())
.ToList();
But the list of parents in the parentFilteredList
it's not of type List<Parent>
.
I need it to be List<Parent>
because the Parent
object in the real case there are a lot of properties, as well as the Child
. Select new
it's not an option.
Any help?
Upvotes: 4
Views: 3775
Reputation: 52240
The basic idea is to use SelectMany, but there are a couple wrinkles depending on assumptions.
Basic code:
var list = parents.SelectMany
(
p => p.ChildrenList.Where( c => c.IsST )
);
The above assumes there are 0 or 1 children per parent that match. If you want to handle the case where a parent has two or more matching children, you'll need one of the variants below.
If you want to throw an exception if a parent has two or more children that match:
var list = parents.SelectMany
(
p => p.ChildrenList.Single( c => c.IsST )
);
If you want to exclude parents that have two children that match:
var list = parents.SelectMany
(
p => p.ChildrenList.SingleOrDefault( c => c.IsST )
?? Enumerable.Empty<Child>()
);
If you want to include the first child that matches:
var list = parents.SelectMany
(
p => p.ChildrenList
.Where( c => c.IsST )
.Take(1)
);
Upvotes: 0
Reputation: 82474
If you are looking to return all the parents where at least one child's ST is true -
var parentFilteredList = parentList
.Where(c => c.ChildrenList.Any(d => d.IsST))
.ToList();
Or if you want to also filter the children's list inside these parents -
var parentFilteredList = parentList
.Where(c => c.ChildrenList.Any(d => d.IsST))
.Select(c =>
{
c.ChildrenList = c.ChildrenList.Where(d => d.IsST).ToList();
return c;
}).ToList();
Note that this will effect your original parents - I'm not sure that's a desirable outcome.
Upvotes: 7
Reputation: 3751
var parentFilteredList = parentList
.Select(c => c.ChildrenList
.Where(d => d.IsST)
.ToList())
.ToList();
In the following statement you are selecting the childrenList.
var parentFilteredList = parentList
.Where(c => c.ChildrenList.Any(d => d.IsST)).ToList();
Upvotes: 4