0

I have this model:

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

    public static List<TreeModel> GetData()
    {
        var list = new List<TreeModel>()
        {
            new TreeModel() {Id = 1,ParentId = null,Name = "Name1"},
              new TreeModel() {Id = 2,ParentId = null,Name = "Name2"},
                new TreeModel() {Id = 3,ParentId = null,Name = "Name3"},
                  new TreeModel() {Id = 4,ParentId = 1,Name = "Name4"},
                    new TreeModel() {Id = 5,ParentId = 1,Name = "Name5"},
                      new TreeModel() {Id = 6,ParentId = 4,Name = "Name6"},
                        new TreeModel() {Id = 7,ParentId = 6,Name = "Name7"},
        };

        return list;
    }

    public static string ShowTree(List<TreeModel> source)
    {
        var text = "";
        foreach (var item in source)
        {
            if (item.ParentId != null) continue;
            text += item.Name + "\n";
            var childs = source.Where(x => x.ParentId == item.Id).ToList();
            if (!childs.Any()) continue;
            {
                foreach (var child in childs)
                {
                    text += "  " + child.Name + "\n"; //2 spaces
                    var childs2 = source.Where(x => x.ParentId == child.Id).ToList();
                    if (!childs2.Any()) continue;
                    {
                        foreach (var child2 in childs2)
                        {
                            text += "    " + child2.Name + "\n"; //4 spaces
                            var childs3 = source.Where(x => x.ParentId == child2.Id).ToList();
                            if (!childs3.Any()) continue;
                            foreach (var child3 in childs3)
                            {
                                text += "      " + child3.Name + "\n"; //6 spaces
                            }
                        }
                    }
                }
            }
        }
        return text;
    }

}

with my method ShowTree, I am able to get this:

Name1
  Name4
    Name6
      Name7
  Name5
Name2
Name3

Can someone help me transform this method in recursive one, in order to use it with a larger data-set.

2
  • See following posting : stackoverflow.com/questions/28976601/… Commented Aug 22, 2016 at 20:54
  • @jdweng my situation is opposite to that question, I have a Tree, and I need to use his data to create a multi-line string in a tree structure. I need this string to use it on a Devexpress XtraReport. Commented Aug 22, 2016 at 21:01

3 Answers 3

2

You need to use a recursive function :

public static string ShowTree(List<TreeModel> source)
{
    var buffer = new StringBuilder();
    foreach (var item in source.Where(x => !x.ParentId.HasValue))
    {
        WriteTree(buffer, source, item);
    }

    return buffer.ToString();
}
private static void WriteTree(StringBuilder buffer, List<TreeModel> source, TreeModel item, int level = 0)
{
    buffer.AppendLine(new string('\t', level) + item.Name);
    foreach (var child in source.Where(x => x.ParentId == item.Id))
    {
        WriteTree(buffer, source, child, level + 1);
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

thank you, your solution is working, the only think is that I cannot use \t (tab)
using new string('\t', level) +1. @LucianBumb just use new string(' ', level * 2)
yes, I know, you both give very good solutions, but I can accept only one
1

Just call the ShowTree method and you will get your formatted data.

Edit: Using StringBuilder because of better performance:

public static string ShowTree(List<TreeModel> source) {
    var empty = new StringBuilder();
    source.Where(s => s.ParentId == null).ToList().ForEach(s => ShowNode(source, s, empty));
    return empty.ToString();
}

private static void ShowNode(List<TreeModel> source, TreeModel model, StringBuilder text, int depth = 0) {
    text.Append(Enumerable.Repeat(" ", depth++).Aggregate("", (s, s1) => s + s1) + model.Name + "\n");

    source.ForEach(m => {
        if (model.Id == m.ParentId) ShowNode(source, m, text, depth);
    });
}

4 Comments

That is one awkward way to pass a string reference around... May I introduce your to ref.
I can't use ref because of the anonnymous function inside ForEach. I'm using StringBuilder now, which is also good for performance.
You could've just used an standard foreach-loop
thank you, your solution is working, and I accepted the answer because you used spaces.
1

Try following code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace ProgrammingBasics
{
    class Program
    {
        static void Main(string[] args)
        {
            TreeModel model = new TreeModel();
            string text = model.ShowTree();
            Console.WriteLine(text);
            Console.ReadLine();
        }
    }
    public class TreeModel
    {
        public int Id { get; set; }
        public int? ParentId { get; set; }
        public string Name { get; set; }

        public static List<TreeModel> GetData()
        {
            var list = new List<TreeModel>()
            {
                new TreeModel() {Id = 1,ParentId = null,Name = "Name1"},
                new TreeModel() {Id = 2,ParentId = null,Name = "Name2"},
                new TreeModel() {Id = 3,ParentId = null,Name = "Name3"},
                new TreeModel() {Id = 4,ParentId = 1,Name = "Name4"},
                new TreeModel() {Id = 5,ParentId = 1,Name = "Name5"},
                new TreeModel() {Id = 6,ParentId = 4,Name = "Name6"},
                new TreeModel() {Id = 7,ParentId = 6,Name = "Name7"},
            };

            return list;
        }
        public string ShowTree()
        {
            int level = 0;
            return ShowTreeRecursive(GetData(), level, null); 
        }

        public static string ShowTreeRecursive(List<TreeModel> source, int level, int? ParentId)
        {
            string text = "";
            foreach(var node in source.Where(x => x.ParentId == ParentId))
            {
                text += string.Format("{0} {1}\n", new string(' ', 3 * level), node.Name);
                text += ShowTreeRecursive(source, level + 1, node.Id);
            }
            return text;
        }
    }

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.