2

I have a large backend DB, which has the following class structure that I'm using:

public class InputClass
{
    public int id { get; set; }
    public string text { get; set; }
    public string icon { get; set; }
    public int? parentId { get; set; }
}

As you can see, each element can have a parent ID, which in the end generates a tree-style list of information that the user can interact with.

Using the following sample data as an example:

var inputList = new List<InputClass>();
inputList.Add(new InputClass() { id = 1, text = "Item #1"});
inputList.Add(new InputClass() { id = 2, text = "Item #2" });
inputList.Add(new InputClass() { id = 3, text = "Item #3" });
inputList.Add(new InputClass() { id = 4, text = "SubItem #1", parentId = 1 });
inputList.Add(new InputClass() { id = 5, text = "SubItem #2", parentId = 1 });
inputList.Add(new InputClass() { id = 6, text = "SubItem #3", parentId = 2 });
inputList.Add(new InputClass() { id = 7, text = "Sub-Sub Item #1", parentId = 4 });

I would like to pass an ID # and retrieve a list of all of the elements marked with that parentID. For example, if I had the ID number of 1, the result should be as follows:

ID  Name
4   Subitem #1
5   Subitem #2
7   Sub-Sub Item #1

as you can see, the result should return everything that sits underneath id #1, including item with ID #7 (even though it has a parent ID of 4, item #4's parent is #1).

I hope the above makes sense, any ideas on how to achieve this in LINQ?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Andrew Milici
  • 145
  • 2
  • 10

4 Answers4

5

Recursive approach.

public static IEnumerable<InputClass> Recursive(List<InputClass> items, int toplevelid)     
{
    List<InputClass> inner = new List<InputClass>();
    foreach (var t in items.Where(item=>item.parentId ==toplevelid))
    {
        inner.Add(t);
        inner = inner.Union(Recursive(items, t.id)).ToList();
    }       

    return inner;
}

Working Demo

Hari Prasad
  • 16,716
  • 4
  • 21
  • 35
2

In this case:

static bool IsParent(IEnumerable<InputClass> lc, InputClass ic, int? ParentID)
{
    return ic.parentId != null ? ic.parentId == ParentID || IsParent(lc, lc.First(o => o.id == ic.parentId), ParentID) : false;
}

int? id = 1; // Parent ID
foreach(var i in inputList)
{
    if(IsParent(inputList, i, id)))
    {
        // get this item
    }
}


Other way:
static IEnumerable<InputClass> getAllChildren(IEnumerable<InputClass> lc, int? ParentID)
{
    foreach (var i in lc)
    {
        if (i.parentId == ParentID)
        {
            yield return i;
            foreach (var i2 in getAllChildren(lc, i.id)) yield return i2;
        }
    }
}

int? id = 1; // Parent ID
foreach (var i in getAllChildren(inputList,id))
{
    // Get this Item
}
NoName
  • 7,940
  • 13
  • 56
  • 108
2
 static class Program
    {
        public static void Main()
        {

            IEnumerable<InputClass> allItems = someBLL.GetAllItems();

            int? someParentNode = 1;

            var allChildItems = InputClass.GetAllChildNodesRecursivrly(someParentNode, allItems);

        }
    }

    public class InputClass
    {
        public int id { get; set; }
        public string text { get; set; }
        public string icon { get; set; }
        public int? parentId { get; set; }

        public static IEnumerable<InputClass> GetAllChildNodesRecursivrly(int? ParentId,IEnumerable<InputClass> allItems)
        {
            var allChilds = allItems.Where(i => i.parentId == ParentId);

            if (allChilds==null)
            {
                return new List<InputClass>();
            }

            List<InputClass> moreChildes = new List<InputClass>();
            foreach (var item in allChilds)
            {
                moreChildes.AddRange(GetAllChildNodesRecursivrly(item.id,allItems));
            }

            return allChilds.Union(moreChildes);
        }
    }
Moumit
  • 8,314
  • 9
  • 55
  • 59
-2

I think that all you need to write is a lambda expression.

var results = inputList.Where(x => x.parentId == 1)
Timothy Macharia
  • 2,641
  • 1
  • 20
  • 27