Duha
Duha

Reputation: 829

Convert list of items to list of tree nodes that have children

I have the following class

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

And the following class for tree view

public class TreeViewModel
{
    public TreeViewModel()
    {
        this.Children = new List<TreeViewModel>();
    }

    public int Id { get; set; }
    public int NodeId { get; set; }
    public string Text { get; set; }
    public bool Expanded { get; set; }
    public bool Checked { get; set; }

    public bool HasChildren
    {
        get { return Children.Any(); }
    }

    public IList<TreeViewModel> Children { get; private set; }
}

I will receive list of items and I would to convert it to tree.

the item that not have parent id it will the main node.

example: if i have the following items

item[0] = Id:0 Text:User ParentId:3

item[1] = Id:1 Text:Role ParentId:3

item[2] = Id:2 Text:SubUser ParentId:0

item[3] = Id:3 Text:Admin ParentId:null

item[4] = Id:4 Text:SuperAdmin ParentId:null

item[5] = Id:5 Text:Doha ParentId:4

the following item it will list of tree

enter image description here

I tried to make recursive function to do that , but i have no result

Upvotes: 3

Views: 1988

Answers (2)

Ivan Stoev
Ivan Stoev

Reputation: 205539

Here is a fast O(N) time complexity method of doing that:

List<Item> list = ...;
// Pre create all nodes and build map by Id for fast lookup
var nodeById = list
    .Select(item => new TreeViewModel { Id = item.Id, Text = item.Text })
    .ToDictionary(item => item.Id);
// Build hierarchy
var tree = new List<TreeViewModel>();
foreach (var item in list)
{
    var nodeList = item.ParentId == null ? tree, nodeById[item.ParentId.Value].Children;
    nodeList.Add(nodeById[item.Id]);
}

Upvotes: 1

James Brierley
James Brierley

Reputation: 4670

You don't need a recursive function to do this:

var models = items.Select(i => new TreeViewModel
{
    Id = i.Id,
    ...
}).ToList();

foreach (var model in models){
    model.Children.AddRange(models.Where(m => m.ParentId == model.Id));
}

If you then want to get the roots of your tree, you can use:

var roots = models.Where(m => !m.ParentId.HasValue);

Upvotes: 2

Related Questions