none
linq ToLookup RRS feed

  • Question

  • Hi

    I have a hierarchy of objects in a collection. root object having parentID = null and children having id = parented.

    ID   ParentID
    
    1     Null
    
    2     1
    
    3     2
    
    4     Null
    
    5     4

    I want a linq query that returns all parent objects excluding the child I start with in a list. I thought

    collection.AsEnumerable().ToLookUp(p=>p.ParentID);

    This parent/ child hierarchy could be multiple levels too.

    can somebody help me out please.


    • Edited by garusher Friday, May 22, 2015 1:48 AM
    Friday, May 22, 2015 1:48 AM

Answers

  • I like using a dictionary.  I also like non-standard for loops like the one below.  Learned from K&R.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("ID",typeof(int));
                dt.Columns["ID"].AllowDBNull = true;
                dt.Columns.Add("ParentID",typeof(int));
                dt.Columns["ParentID"].AllowDBNull = true;
                dt.Rows.Add(new object[] { 1, null });
                dt.Rows.Add(new object[] {2, 1});
                dt.Rows.Add(new object[] {3, 2});
                dt.Rows.Add(new object[] {4, null});
                dt.Rows.Add(new object[] {5, 4});
    
                Dictionary<int, DataRow> dict = dt.AsEnumerable()
                    .GroupBy(x => x.Field<int>("ID"), y => y)
                    .ToDictionary(x => x.Key, y => y.FirstOrDefault());
    
                List<DataRow> parents = new List<DataRow>();
                int childID = 3;
                for (DataRow row = dict[childID]; row.Field<int?>("ParentID") != null; row = dict[row.Field<int>("ParentID")])
                {
                    parents.Add(dict[childID]);
                }
    
            }
        }
    }


    jdweng


    Friday, May 22, 2015 12:37 PM

All replies

  • "I want a linq query that returns all parent objects excluding the child I start with in a list."

    That is, all the ancestors of a node? 2 and 1 for node 3 and 4 for node 5?

    LINQ queries aren't suitable for this kind of problem. Just use a some type of loop (for, while) to walk the parent chain. Since for every parent ID you'll need to locate the corresponding entry in the list you can consider using ToLookup as you did to build a lookup object that speeds up finding the entries by ID. But by itself ToLookup has nothing to do with what you're trying to do.

    Friday, May 22, 2015 6:59 AM
    Moderator
  • I want a linq query that returns all parent objects excluding the child I start with in a list.

    Hi,

    Could you please explain what this phrase mean?


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Friday, May 22, 2015 9:40 AM
    Moderator
  • I want a linq query that returns all parent objects excluding the child I start with in a list.

    Hi,

    Could you please explain what this phrase mean?


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    since this is a tree structure then if I had an object with ID = 3 and ParentID = 2 I would like to find the objects parents and then the parents parents etc. but I do not want the object I started with to be in the returned list. I guess the ToLookUp(parentID).where(z=>z.ID != 3)

    Friday, May 22, 2015 11:20 AM
  • I like using a dictionary.  I also like non-standard for loops like the one below.  Learned from K&R.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Data;
    
    namespace ConsoleApplication1
    {
        class Program
        {
            static void Main(string[] args)
            {
                DataTable dt = new DataTable();
                dt.Columns.Add("ID",typeof(int));
                dt.Columns["ID"].AllowDBNull = true;
                dt.Columns.Add("ParentID",typeof(int));
                dt.Columns["ParentID"].AllowDBNull = true;
                dt.Rows.Add(new object[] { 1, null });
                dt.Rows.Add(new object[] {2, 1});
                dt.Rows.Add(new object[] {3, 2});
                dt.Rows.Add(new object[] {4, null});
                dt.Rows.Add(new object[] {5, 4});
    
                Dictionary<int, DataRow> dict = dt.AsEnumerable()
                    .GroupBy(x => x.Field<int>("ID"), y => y)
                    .ToDictionary(x => x.Key, y => y.FirstOrDefault());
    
                List<DataRow> parents = new List<DataRow>();
                int childID = 3;
                for (DataRow row = dict[childID]; row.Field<int?>("ParentID") != null; row = dict[row.Field<int>("ParentID")])
                {
                    parents.Add(dict[childID]);
                }
    
            }
        }
    }


    jdweng


    Friday, May 22, 2015 12:37 PM