Reputation: 278
I have two lists, a parent list (parents) and a child list (children) with the child list having a parentId.
List<Parent> parents
List<Child> children
I am trying to combine the two lists into a single list of parents with each parent object having a list of children. I'm currently looping through the parent list and populating the Children list within each parent object based on the parentId but I was wondering if there was a faster way to do this using LINQ.
foreach (var parent in parents)
{
parent.Children = children.Where(c=>c.ParentId == parent.Id).ToList();
}
Any suggestions?
Upvotes: 0
Views: 1806
Reputation: 413
I know it is an old question but I'd like to share my experience
for me I have a lot of records in database so the performance is important I crate it in another way and get the result about 3 times faster. I get all data in one select then put results in my models.
I have restaurant database with menus and dishes tables.
At first these are the classes models that will handle the selected data and are different from database models
public class Menu
{
public Menu()
{
Dishes = new List<Dish>();
}
public long ID { get; set; }
public string Name { get; set; }
public string ImagePath { get; set; }
public List<Dish> Dishes { get; set; }
}
public class Dish
{
public long ID { get; set; }
public string Name { get; set; }
public string PicturePath { get; set; }
public double Price { get; set; }
}
This is the Linq query
var all = (from m in contexts.RestMenus
join d in contexts.ResDishes on m.Id equals d.MenuID
select new
{
Menu = new Menu()
{
ID = m.MenuID,
Name = m.Name,
ImagePath = m.ImageURL
},
Dish = new Dish()
{
ID = d.ItemID,
Name = d.Name,
PicturePath = d.PicturePath,
Price = d.DefaultPrice
}
}).ToList();
and the foreach loop to arrange the data
List<Menu> menus = new List<Menu>();
foreach (var r in all)
{
Menu m = menus.Find(x => x == r.Menu);
if (m == null)
{
menus.Add(r.Menu);
m = r.Menu;
}
m.Dishes.Add(r.Dish);
}
Upvotes: 1
Reputation: 93
From a performance point of view there is nothing wrong with your foreach.
If your code is readable enough there is no point to make your code linq and fancy.
If your collections are very large, from performance perspective it might be most efficient if you firstly group your children by parent id and sort groups by parent id and get them appended to the sorted parents.
Upvotes: 1
Reputation: 14007
You can use a Join
, combined with a GroupBy
:
var parentChildrenQry =
from parent in parents
join child in children on parent.Id equals child.ParentId
group child by parent;
foreach(var grp in parentChildrenQry) {
grp.Key.Children = grp.ToList();
}
Or both in one statement with GroupJoin
:
var parentChildrenQry =
parents.GroupJoin(children, parent.Id, child.ParentId, new { (parent, childGrp) => new { Parent = parent, Children = childGrp.ToList() } );
foreach(var grp in parentChildrenQry) {
grp.Parent.Children = grp.Children;
}
Upvotes: 3