列表<对象>的递归读取
本文关键字:递归 读取 对象 列表 | 更新日期: 2023-09-27 18:36:08
我有List<Object>
的结构,具体来说它是一个"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
我的问题是,我如何步入我声明的每个"类别项"对象:
List<CategoryItem> categoryItems = new List<CategoryItem>();
这样我就可以像这样在 html 的无序列表中显示它
- 欢迎北卡罗来纳州
- 数控
- 生产
- 行政
- NPower
- 帮助
- 7
- 查尔克
- 7
- 第一
有没有办法做到这一点?
如果您的 CategoryItem 不包含其子项的列表(如问题的第一个版本),我将首先构建一个字典,为每个 CategoryID 提供所有子类别项,然后使用此字典递归打印所有项目,并从父项"0"开头。假设 Print 是打印与项目关联的数据的指令,并且它将缩进级别作为唯一参数,则代码将如下所示:
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);
}
}
也许看看 TreeView 控件? http://msdn.microsoft.com/en-US/library/7A9swst5(v=vs.80).aspx
ASP.NET TreeView 控件旨在以分层结构向用户显示数据。用户可以打开单个节点,而这些节点又可以包含子节点。控件适用于显示 XML 数据,但可用于可在层次结构中表示的任何数据。
我想这将是你想要的。
否则,需要循环访问列表中的每个项目,并递归处理每个可能具有也可能没有更多子项的子项。 这很棘手,但只是一开始。
一个简单但不是最优但简单的解决方案是迭代列表,对于每个项目,您计算在 0 之前调用其父 id 的次数。因此,您就知道您的<li>
必须具有多少级标识。
您需要创建一个"呈现"类别项的递归方法。此方法需要知道级别或当前深度,以便呈现以更正缩进:
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);
}
}
阅读递归。那里有相当多的样本。维基百科上的那些很简单,但原理是相同的:在一个"级别"上解决问题,然后在每个子级别上递归调用相同的方法。