C# 在文本树中表示自引用表

C# 在文本树中表示自引用表,c#,algorithm,tree,self-referencing-table,C#,Algorithm,Tree,Self Referencing Table,我想在文本树中表示一个自引用表(类似于TreeView,但使用文本)。我一直在努力,到目前为止我做得很好。问题是当我在树上深入几层时。到目前为止,结果是: ┌──Main Group 1 │ ├──SubGroup 1.1 │ │ ├──SubGroup 1.1.1 │ │ ├──SubGroup 1.1.2 │ │ ├──SubGroup 1.1.3 │ │ └──SubGroup 1.1.4 │ │ ├──SubGroup 1.1.4.1 │ │ └──

我想在文本树中表示一个自引用表(类似于TreeView,但使用文本)。我一直在努力,到目前为止我做得很好。问题是当我在树上深入几层时。到目前为止,结果是:

┌──Main Group 1
│  ├──SubGroup 1.1
│  │  ├──SubGroup 1.1.1
│  │  ├──SubGroup 1.1.2
│  │  ├──SubGroup 1.1.3
│  │  └──SubGroup 1.1.4
│  │     ├──SubGroup 1.1.4.1
│  │     └──SubGroup 1.1.4.2
│  │  │     ├──Problem group 1
│  │  │     ├──Problem group 2
│  │  │     └──Problem group 3
│  │  │  │     └──Problem group 3.1
│  ├──SubGroup 1.2
│  └──SubGroup 1.3
│     ├──SubGroup 1.3.1
│     └──SubGroup 1.3.2
└──Main Group 2
   ├──SubGroup 2.1
   └──SubGroup 2.2
正如您在上面的
问题组中所看到的,格式开始中断,并显示额外的行

我写的代码是:

public class Group
    {
        public int ID { get; set; }
        public int? ParentID { get; set; }
        public string Name { get; set; }
    }

    static void Main(string[] args)
    {
        List<Group> groups = new List<Group>();
        groups.Add(new Group { ID = 1, ParentID = null, Name = "Main Group 1" });
        groups.Add(new Group { ID = 2, ParentID = 1, Name = "SubGroup 1.1" });
        groups.Add(new Group { ID = 3, ParentID = 1, Name = "SubGroup 1.2" });
        groups.Add(new Group { ID = 4, ParentID = 1, Name = "SubGroup 1.3" });
        groups.Add(new Group { ID = 5, ParentID = null, Name = "Main Group 2" });
        groups.Add(new Group { ID = 6, ParentID = 5, Name = "SubGroup 2.1" });
        groups.Add(new Group { ID = 7, ParentID = 5, Name = "SubGroup 2.2" });
        groups.Add(new Group { ID = 8, ParentID = 2, Name = "SubGroup 1.1.1" });
        groups.Add(new Group { ID = 9, ParentID = 2, Name = "SubGroup 1.1.2" });
        groups.Add(new Group { ID = 10, ParentID = 2, Name = "SubGroup 1.1.3" });
        groups.Add(new Group { ID = 11, ParentID = 2, Name = "SubGroup 1.1.4" });
        groups.Add(new Group { ID = 12, ParentID = 11, Name = "SubGroup 1.1.4.1" });
        groups.Add(new Group { ID = 13, ParentID = 11, Name = "SubGroup 1.1.4.2" });
        groups.Add(new Group { ID = 14, ParentID = 13, Name = "Problem group 1" });
        groups.Add(new Group { ID = 15, ParentID = 13, Name = "Problem group 2" });
        groups.Add(new Group { ID = 16, ParentID = 13, Name = "Problem group 3" });
        groups.Add(new Group { ID = 17, ParentID = 16, Name = "Problem group 3.1" });
        groups.Add(new Group { ID = 18, ParentID = 4, Name = "SubGroup 1.3.1" });
        groups.Add(new Group { ID = 19, ParentID = 4, Name = "SubGroup 1.3.2" });

        PrintGroupsTree(groups);
        Console.Read();
    }


    static void PrintGroupsTree(List<Group> groups)
    {
        if (groups == null)
            return;

        var rootGroups = groups.Where(grp => grp.ParentID == null);

        foreach (var g in rootGroups)
            PrintRow(0, g, groups);
    }

    private static void PrintRow(int p, Group grp, List<Group> groups)
    {
        string leader = string.Empty;
        string leaderEnd = string.Empty;

        // get the root items
        var rootItems = groups.Where(g => g.ParentID == null);

        // find the leading character
        if (grp == rootItems.First())
        {
            if (rootItems.Count() == 1)
                leader = "─";
            else
                leader = "┌";
        }
        else if (grp == rootItems.Last())
        {
            leader = "└";
        }
        else
        {
            if (p == 0)
                leader = "├";
            else
                if (rootItems.Count() == 1)
                    leader += " ";
                else
                    leader = "│";
        }

        if (grp.ParentID == rootItems.Last().ID)
            leader = " ";

        // if this is a child node
        if (!rootItems.Contains(grp))
        {
            // get the siblings of the current node (same parentID)
            var itemSiblings = groups.Where(g => g.ParentID == grp.ParentID);
            if (grp == itemSiblings.Last())
                leaderEnd = " └";
            else
                leaderEnd = " ├";
        }

        // get the siblings of the parent item (same as parentItem.ParentID)
        var parentItem = groups.Where(g => g.ID == grp.ParentID).SingleOrDefault();
        var parentItemSiblings = groups.Where(g => g.ParentID == parentItem.ParentID);
        if (p > 0)
        {
            leader += " ";
            for (int i = 1; i <= p - 1; i++)
            {
                if (!rootItems.Contains(grp)
                    && parentItem == parentItemSiblings.Last()
                    && i == p - 1)
                    leader += "   ";

                else
                    leader += " │ ";
            }
        }

        // write the group
        string row = leader + leaderEnd + "──" + grp.Name;
        Console.WriteLine(row);

        // recursive calling to the childs of this item
        var childGroups = groups.Where(g => g.ParentID == grp.ID);
        foreach (var g in childGroups)
        {
            PrintRow(p + 1, g, groups);
        }
    }
公共类组
{
公共int ID{get;set;}
public int?ParentID{get;set;}
公共字符串名称{get;set;}
}
静态void Main(字符串[]参数)
{
列表组=新列表();
添加(新组{ID=1,ParentID=null,Name=“Main Group 1”});
添加(新组{ID=2,ParentID=1,Name=“subgroup1.1”});
添加(新组{ID=3,ParentID=1,Name=“subgroup1.2”});
添加(新组{ID=4,ParentID=1,Name=“subgroup1.3”});
Add(新组{ID=5,ParentID=null,Name=“Main Group 2”});
添加(新组{ID=6,ParentID=5,Name=“subgroup2.1”});
添加(新组{ID=7,ParentID=5,Name=“subgroup2.2”});
添加(新组{ID=8,ParentID=2,Name=“subgroup1.1.1”});
添加(新组{ID=9,ParentID=2,Name=“subgroup1.1.2”});
添加(新组{ID=10,ParentID=2,Name=“subgroup1.1.3”});
添加(新组{ID=11,ParentID=2,Name=“subgroup1.1.4”});
添加(新组{ID=12,ParentID=11,Name=“subgroup1.1.4.1”});
添加(新组{ID=13,ParentID=11,Name=“subgroup1.1.4.2”});
添加(新组{ID=14,ParentID=13,Name=“Problem Group 1”});
添加(新组{ID=15,ParentID=13,Name=“问题组2”});
添加(新组{ID=16,ParentID=13,Name=“问题组3”});
添加(新组{ID=17,ParentID=16,Name=“问题组3.1”});
添加(新组{ID=18,ParentID=4,Name=“subgroup1.3.1”});
添加(新组{ID=19,ParentID=4,Name=“subgroup1.3.2”});
打印组(组);
Console.Read();
}
静态void打印组stree(列表组)
{
如果(组==null)
返回;
var rootGroups=groups.Where(grp=>grp.ParentID==null);
foreach(根组中的var g)
PrintRow(0,g,组);
}
私有静态void PrintRow(int p、Group grp、List Group)
{
字符串引线=string.Empty;
string leaderEnd=string.Empty;
//获取根项目
var rootItems=groups.Where(g=>g.ParentID==null);
//找到主角
if(grp==rootItems.First())
{
if(rootItems.Count()==1)
领导=”─";
其他的
领导=”┌";
}
else if(grp==rootItems.Last())
{
领导=”└";
}
其他的
{
如果(p==0)
领导=”├";
其他的
if(rootItems.Count()==1)
前导+=“”;
其他的
领导=”│";
}
if(grp.ParentID==rootItems.Last().ID)
leader=“”;
//如果这是一个子节点
如果(!rootItems.Contains(grp))
{
//获取当前节点的同级(相同的父ID)
var itemshibles=groups.Where(g=>g.ParentID==grp.ParentID);
if(grp==itemshibles.Last())
leaderEnd=”└";
其他的
leaderEnd=”├";
}
//获取父项的同级项(与parentItem.ParentID相同)
var parentItem=groups.Where(g=>g.ID==grp.ParentID).SingleOrDefault();
var parentItemSides=groups.Where(g=>g.ParentID==parentItem.ParentID);
如果(p>0)
{
前导+=“”;
for(inti=1;ig.ParentID==grp.ID);
foreach(子组中的变量g)
{
PrintRow(p+1,g,组);
}
}

有没有一种方法可以使用外观更好的代码正确地表示这一点?

这是一个需要递归的问题,您没有充分利用它

    static void Main(string[] args)
    {     
        List<Group> groups = new List<Group>();               
        ...
        PrintTree(groups, "", null);
    }

    static void PrintTree(List<Group> allGroups, string lead, int? id)
    {
        var children = allGroups.Where(g => g.ParentID == id).ToList();

        if (children.Count > 0)
        {
            int n = children.Count-1;

            for (int i = 0; i < n; i++)
            {
                Console.WriteLine(lead + "├──" + children[i].Name);
                PrintTree(allGroups, lead + "│  ", children[i].ID);                    
            }

            Console.WriteLine(lead + "└──" + children[n].Name);
            PrintTree(allGroups, lead + "   ", children[n].ID);                    
        }
    }
static void Main(字符串[]args)
{     
列表组=新列表();
...
打印树(组“”,空);
}
静态void打印树(列出所有组、字符串引线、int?id)
{
var children=allGroups.Where(g=>g.ParentID==id.ToList();
如果(children.Count>0)
{
int n=children.Count-1;
对于(int i=0;i

我把修复第一个元素作为一项练习。

树和递归很有趣,但需要一些练习。坚持下去。