Reputation: 4342
Having a list of type A, each containing a list of type B, what's the best way to get a list of all type B, each containing a list of type A to which they belong?
Having a list like the following:
var parents = new List<Parent> {
{
new Parent {
ID = 1,
Childs = new List<Child> {
{
new Child {
ID = 1
}
},
{
new Child {
ID = 2
}
},
{
new Child {
ID = 3
}
}
}
}
},
{
new Parent {
ID = 2,
Childs = new List<Child> {
{
new Child {
ID = 3
}
},
{
new Child {
ID = 4
}
},
{
new Child {
ID = 5
}
}
}
}
}
};
I would like to query this to receive the following result:
[
{
Child = 1,
InParent = [1]
},
{
Child = 2,
InParent = [1]
},
{
Child = 3,
InParent = [1, 2]
},
{
Child = 4,
InParent = [2]
},
{
Child = 5,
InParent = [2]
},
]
EDIT: I tried an approach to flatten the childs first using SelectMany
& Distinct
, but not sure how to link this to the parent again:
var foo =
from childId in parents.SelectMany(x => x.Childs).Select(x => x.ID).Distinct()
select
new
{
childId = childId,
inParent = // Missing Part
};
Upvotes: 3
Views: 1285
Reputation: 460158
You have to use SelectMany
first to flatten them, then use GroupBy
to group by child-id and String.Join
to concat each parent-id:
var childParents = parents
.SelectMany(p => p.Childs.Select(c => new {Parent = p, Child = c}))
.GroupBy(x => x.Child.ID)
.Select(g => new
{
Child = g.Key,
InParent = String.Join(", ", g.Select(x => x.Parent.ID))
});
Result:
If you actually don't want that InParent
property is a string but a List<int>
(or array) use this:
.....
InParent = g.Select(x => x.Parent.ID).ToList() // or ToArray()
Upvotes: 8
Reputation: 3
I guess you should try changing your data model if you are looking for storing tree like structure, in that scenario you should always use single Linked List with custom object & nested reference to corresponding parent / child in the similar way you store in database.
It is an ideal way to handle data structures of such kind as such otherwise you will end up in many nested queries.
Upvotes: -1
Reputation: 172280
You can split your large problem into two simpler problems:
Create an anonymous object for each parent/child pair, containing a reference to the parent as well as to the child. You can use a simple LINQ query with two from
clauses for that.
Group those objects into the representation you need. The group by
clause is your friend here.
Upvotes: 0