名单的递归阅读(Recursive reading of List<Object>)

2019-06-25 04:21发布

我有这种结构List<Object> ,具体而言这是一个“CategoryItem”对象。 这里是我的“CategoryItem”对象的声明。

public class CategoryItem
{
    public string Name { get; set; }
    public int CategoryID {get; set;}
    public int ParentID {get; set; }
    public List<CategoryItem> SubCategory {get; set;}
}

这里是我的样本数据结构:

[0] CategoryID: 249
Name: "WelcomeNC"
ParentID: 0
SubCategory: length=4
    [0] CategoryID: 250
        Name: "CNC"
        ParentID: 249
        SubCategory: length=0
    [1] CategoryID: 251
        Name: "Production"
        ParentID: 249
        SubCategory: length=0
    [2] CategoryID: 252
        Name: "Administrative"
        ParentID: 249
        SubCategory: length=1
            [0] CategoryID: 261
                Name: "NPower"
                ParentID: 252
                SubCategory: length=0
    [3] CategoryID: 253
        Name: "Help"
        ParentID: 249
        SubCategory: length=1
            [0] CategoryID: 254
                Name: "7"
                ParentID: 253
                SubCategory: length=1
                    [0] CategoryID: 255
                        Name: "CHLK"
                        ParentID: 254
                        SubCategory: length=0
[1] CategoryID: 111
Name: "First"
ParentID: 0
SubCategory: length=0

我的问题是,如何我在宣布每个“CategoryItem”对象步骤:

List<CategoryItem> categoryItems = new List<CategoryItem>();

所以,我可以在这样的HTML无序列表显示出来

  • WelcomeNC
    • CNC
    • 生产
    • 行政的
      • 甲级
    • 救命
      • 7
        • CHLK
  • 第一

有没有办法做到这一点?

Answer 1:

如果您CategoryItem不包含(像这个问题的第一个版本),其子女的名单,我想首先是构建的foreach类别ID给你所有的子类项的字典,然后递归使用这本字典打印所有项目并开始与父母“0”的项目。 假设打印是打印与项目相关的数据的指令,而且,它需要作为唯一的参数缩进的水平,代码如下所示:

    public static void PrintItems(List<CategoryItem> items)
    {
        Dictionary<string, List<CategoryItem>> dictOfChildren = new Dictionary<string, List<CategoryItem>>();
        // loop through all the items grouping them according to their ParentID
        foreach (CategoryItem anItem in items)
        {
            List<CategoryItem> children;
            if (!dictOfChildren.TryGetValue(anItem.ParentID, out children))
            {
                children = new List<CategoryItem>();
                dictOfChildren[anItem.ParentID] = children;
            }
            children.Add(anItem);
        }
        // recursively print all the items starting from the ones with ParentID = 0
        // the dictionary is passed to the method in order to be able to find the children of each item
        PrintItems(dictOfChildren["0"], dictOfChildren, 0);
    }

    private static void PrintItems(List<CategoryItem> list, Dictionary<string, List<CategoryItem>> dictOfChildren, int levelOfIndentation)
    {
        foreach (CategoryItem anItem in list)
        {
            // first print the current item
            anItem.Print(levelOfIndentation);
            // then recursively print all its children
            List<CategoryItem> children;
            if (dictOfChildren.TryGetValue(anItem.CategoryID, out children) &&
                children.Count > 0)
                PrintItems(children, dictOfChildren, levelOfIndentation + 1);
        }
    }

这不是真正的面向对象的,但是这应该给你要遵循的方向提示。

编辑:

我看到你编辑的问题,现在你已经添加的子类别属性。 这使得事情变得简单,你可以简单地这样做:

public static void PrintItems(List<CategoryItem> items)
{
    // call a recursive method passing 0 as level of indentation
    PrintItems(items, 0);
}

public static void PrintItems(List<CategoryItem> items, int levelOfIndentation)
{
    foreach (CategoryItem anItem in items)
    {
        // print the currentItem
        anItem.Print(levelOfIndentation);
        // increment the level of indentation and callk the same method for the children
        PrintItems(anItem.SubCategory, levelOfIndentation + 1);
    }
}


Answer 2:

也许看看TreeView控件? http://msdn.microsoft.com/en-us/library/7a9swst5(v=vs.80).aspx

的ASP.NET TreeView控件被设计成呈现与数据用户在分层结构。 用户可以打开,可又包含子节点单独的节点。 树视图控制是适合于显示XML数据,但也可以用于可以在层次结构中表示的任何数据。

我认为这将是你想要的。

否则,它是通过每个项目在列表中的迭代和递归处理可能会或可能不会有更多的子项的每个子项的问题。 这是棘手的,但只有在第一。



Answer 3:

简单不是最优的,但简单的解决方法是将只是遍历列表,并为每个项目你算你多少次调用它的父ID是它的0,那么你知道你的identation多少水平之前<li>必须有。



Answer 4:

您需要创建一个递归方法“呈现”一类的项目。 此方法需要知道以水平或当前深度的渲染来纠正缩进:

private void RenderCategory(HtmlTextWriter writer, CategoryItem item, int level)
{
  writer.Write("<li style='padding-left: {0}px'>{1}</li>", 
    level * 5,
    HttpUtility.HtmlEncode(item.Name));

  int nextLevel = ++level;
  foreach (CategoryItem child in item.SubCategories)
  { 
    RenderCategory(writer, child, nextLevel);
  }
}


Answer 5:

阅读上的递归 。 有相当多的样品在那里。 维基百科上的那些很简单,但原理是一样的:解决这个问题的一个“级别”,然后递归调用相同的方法在每个分段。



文章来源: Recursive reading of List