mohsinali1317
mohsinali1317

Reputation: 4425

C# get hierarchical list by recursion

In my Azure table I have a tree like structure. What I am trying to achieve is to get a list of data like this

var data = [{

 item1 : {
   name : "",
   children : [] // list of children, if any children is a parent of other items get those
 }
}]

I have written this code

 List<dynamic> test = new List<dynamic>();
 DisplayTree(NewMassType.GetAll().Where(e => e.ParentId == null), test);


    public void DisplayTree(IEnumerable<NewMassType> elements, List<dynamic> test)
    {
        foreach (var element in elements)
        {
            test.Add(new
            {
                name = element.Name
            });

            var children = NewMassType.GetAll().Where(e => e.ParentId == element.Id);
            if (children.Count() > 0)
            {
                DisplayTree(children,test);
            }

        }
    }

It gives me a flat list out. Looking forward for suggestions.

Upvotes: 2

Views: 4993

Answers (2)

Joel Etherton
Joel Etherton

Reputation: 37533

The reason it gives you a flat list is because you're passing in the top level collection each time.

DisplayTree(children,test);

What this does is it just appends the children to the end of the list. What you really need is an alternate method that specifically populates the children rather than the top level.

List<dynamic> test = NewMassType.GetAll().Where(e => e.ParentId == null);

foreach (var element in test)
{
    PopulateChildren(element);
}

// Somewhere down the line have a method

public void PopulateChildren(dynamic element) 
{
    var children = NewMassType.GetAll().Where(e => e.ParentId == element.Id);

    element.children = children;

    foreach (var child in element.children)
    {
         PopulateChildren(child);
    }        
}

You have to make sure each parent/child assignment happens at the right place as its done otherwise you'll keep getting a flat list.

Note: I've changed some of the data types here to use dynamic as you've done, but I really recommend creating an enforced type to hold the structure you want rather than relying on anonymous types.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726519

In order to build a hierarchy you need to store the results inside hierarchy, not inside a flat list. Your recursive approach needs to be reworked:

static List<dynamic> DisplayTree(IEnumerable<NewMassType> elements) {
    var res = new List<dynamic>();
    foreach (var element in elements) {
        var children = DisplayTree(NewMassType.GetAll().Where(e => e.ParentId == element.Id)).ToArray();
        if (children.Length != 0) {
            res.Add(new {
                name = element.Name
            ,   children = children
            })
        } else {
            res.Add(new {
                name = element.Name
            })
        }
    }
    return res;
}

The key difference between this code and your code is that each recursive invocation produces a separate list, which is added to objects of the anonymous type when it is not empty.

Upvotes: 3

Related Questions