Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
128 views
in Technique[技术] by (71.8m points)

linq - C#- Get childs upto given depth

I have a list that contains parent child relation and I want to get children upto defined length:

Given the following class:

public class Item
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int ParentId { get; set; }
}

Here is the list:

var list = new List<Item>();
list.Add(new Item { Id = 1, Name = "Parent", ParentId = 0 });
list.Add(new Item { Id = 2, Name = "Child1", ParentId = 1 });
list.Add(new Item { Id = 3, Name = "Child2", ParentId = 1 });
list.Add(new Item { Id = 4, Name = "GrandChild1", ParentId = 2 });
list.Add(new Item { Id = 5, Name = "GrandChild2", ParentId = 2 });
list.Add(new Item { Id = 6, Name = "GrandChild3", ParentId = 3 });
list.Add(new Item { Id = 7, Name = "GrandChild4", ParentId = 3 });
list.Add(new Item { Id = 8, Name = "GrandGrandChild1", ParentId = 4 });
list.Add(new Item { Id = 9, Name = "GrandGrandChild2", ParentId = 5 });
list.Add(new Item { Id = 10, Name = "GrandGrandChild3", ParentId = 6 });
list.Add(new Item { Id = 11, Name = "GrandGrandChild4", ParentId = 7 });

Now I want that if I pass depth=0 in url then it will return all data but if I pass depth=1 then it will return string like:

"Parent:Child1:GrandChild1:GrandGrandChild1"
"Parent:Child1:GrandChild2:GrandGrandChild2"

and if I pass depth=2 then:

"Parent:Child1:GrandChild1:GrandGrandChild1"

I have tried this code:

public void Traverse(List<Item> list)
{
    var parentIds = list.Where(e => e.ParentId > 0).Select(e => e.ParentId).ToList();

    var bargs = list.Where(e => !parentIds.Contains(e.Id)).ToList();

    foreach (var item in bargs)
    {
        Traverse(list, item);
    }
}

private void Traverse(List<Item> items, Item item)
{
    var list = new List<Item> { item };

    int id = item.ParentId;

    while (true)
    {
        var found = items.Where(e => e.Id == id).FirstOrDefault();
        list.Insert(0, found);

        if(found.ParentId == 0) { break; }

        id = found.ParentId;
    }

    var str = string.Empty;
    foreach (var node in list)
    {
        str += node.Name;
        if(node != item) { str += ":"; }
    }

    Console.WriteLine(str);
}

Now this code returns the desired strings successfully but I can't figure out how can I add depth check in "items". Depth can be "n" so I can't add if else. Any help?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Refer to the function below :

    /// <summary>
    /// Function to get the string representations of the hierarchy List
    /// </summary>
    /// <param name="Items">The hierarchical list of items</param>
    /// <param name="rootItem">The item whose children are to be traversed</param>
    /// <param name="depth">Depth to which the function should traverse. Passsing zero will make the function traverse throughout the heirarchy</param>
    /// <returns>List of string representing each hierarchy</returns>
    public List<string> GetChildren(List<Item> Items, Item rootItem, int depth)
    {
        List<string> ReturnList = new List<string>();

        TraverseChildren(Items, rootItem, depth, 1, ReturnList, rootItem.Name);

        return ReturnList;
    }

    private void TraverseChildren(List<Item> items, Item rootItem, int depth, int currentLevel, List<string> hierarchyList, string hierarchyString)
    {
        // Return If current level is higher than Depth
        // And depth is non-zero
        if (currentLevel > depth && depth !=0) { return; }

        Item[] Children = items.Where(x => x.ParentId == rootItem.Id).ToArray();

        foreach (Item itm in Children)
        {
            string currentItemHeirarchyString = string.Format("{0}:{1}", hierarchyString, itm.Name);
            hierarchyList.Add(currentItemHeirarchyString);

            TraverseChildren(items, itm, depth, currentLevel + 1, hierarchyList, currentItemHeirarchyString);
        }
    }

Sample usage :

        // Get the item whose children to be traveresed
        Item RootItem = list.FirstOrDefault(x => x.Name == "Child1");
        GetChildren(list, RootItem, 1);

The result will be

Child1:GrandChild1
Child1:GrandChild2

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...