If you have a tree for walking, you already have items grouped into categories. Do you control the interface of your kind?
public abstract class TreeNode { private readonly int name; private Category c = null; public int Name { get { return name; } } public Category Parent { get { return c; } } public abstract string Tag { get; } public TreeNode(int n, Category c) { this.name = n; AssignCategory(c); } public void AssignCategory(Category c) { if (c != null) { this.c = c; c.AddChild(this); } } public virtual IList<TreeNode> Children { get { return null; } } }
The item and category look like
public class Item : TreeNode { public Item(int n, Category c) : base(n, c) {} public override string Tag { get { return "Item"; } } } public class Category : TreeNode { List<TreeNode> kids = new List<TreeNode>(); public Category(int n, Category c) : base(n, c) {} public void AddChild(TreeNode child) { kids.Add(child); } public override string Tag { get { return "Category"; } } public override IList<TreeNode> Children { get { return kids; } } }
Then you can show them, say, with a console display:
public class CornyTextView { public int NodeDepth(TreeNode n) { if (n.Parent == null) return 0; else return 1 + NodeDepth(n.Parent); } public void Display(IEnumerable<TreeNode> nodes) { foreach (var n in nodes.OrderBy(n => n.Name)) { for (int i = 0; i < NodeDepth(n); i++) Console.Write(" "); Console.WriteLine("- " + n.Tag + " " + n.Name.ToString()); if (n.Children != null) Display(n.Children); } } }
So, to generate the output for your example:
public static void Main() { var cats = new [] { new Category(1, null), new Category(2, null), new Category(3, null), new Category(4, null), new Category(5, null), }; cats[2].AssignCategory(cats[1]); var items = new[] { new Item(6, cats[4]), new Item(5, cats[3]), new Item(3, cats[2]), new Item(4, cats[2]), new Item(1, cats[0]), new Item(2, cats[0]), }; new CornyTextView() .Display(cats.Where(c => c.Parent == null) .Select(c => c as TreeNode)); }
Please note that even if items shuffled, the output
- Category 1
- Item 1
- Item 2
- Category 2
- Category 3
- Item 3
- Item 4
- Category 4
- Item 5
- Category 5
- Item 6