hines
hines

Reputation: 278

Combine Parent and Child Lists into a single nested Parent List

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

Answers (3)

Abdu Imam
Abdu Imam

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

Farrah Jiang
Farrah Jiang

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

Sefe
Sefe

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

Related Questions