C# 如何搜索自定义类的所有嵌套子类?
我在数据库中有一个表,如下所示:C# 如何搜索自定义类的所有嵌套子类?,c#,C#,我在数据库中有一个表,如下所示: | id | parentID | name | |----------+----------+-------------| |ABCD-12345| | Top | |----------+----------+-------------| |ABCD-23456|ABCD-12345| Middle | |----------+----------+-------------| |ABCD
| id | parentID | name |
|----------+----------+-------------|
|ABCD-12345| | Top |
|----------+----------+-------------|
|ABCD-23456|ABCD-12345| Middle |
|----------+----------+-------------|
|ABCD-34567|ABCD-23456| Bottom |
|----------+----------+-------------|
|ABCD-45678|ABCD-23456| Bottom |
等等——基本上是N深度的层次结构。我把它放到了一个数据表中
static List<DataTableData> GetDataTableData()
{
var data = new List<DataTableData>
{
new DataTableData() { Id = "23456", ParentID = "12345", Name = "Middle" },
new DataTableData() { Id = "55555", ParentID = "12345", Name = "Middle" },
new DataTableData() { Id = "34567", ParentID = "23456", Name = "Bottom" },
new DataTableData() { Id = "12345", ParentID = string.Empty, Name = "Top" },
new DataTableData() { Id = "45678", ParentID = "23456", Name = "Bottom" },
new DataTableData() { Id = "66666", ParentID = "55555", Name = "Bottom" }
};
return data;
}
我构建了以下类来保存这些数据:
public class TreeNode
{
public string id { get; set; }
public string name { get; set; }
public string parentID { get; set; }
public List<TreeNode> children { get; set; }
}
它获取一个超出范围的异常,因为我在索引0处有一个根,所以在第二次运行时(当currNode
为1时),它会中断。我需要遍历到treeList[0]。Children[int]
,然后是treeList[0]。Children[int]。Children[int]
等等
那么我如何实现这个目标呢?首先,为了方便起见,我将修改
TreeNode
类。这不是必须的,只是一个很好的选择。另外,我将假设在您的数据表中,您已经完成了错误检查,并且只有一个节点具有ParentId=“”
这就是您的Main()
的外观:
static void Main(string[] args)
{
var treeNodes = new List<TreeNode>();
var dataTable = GetDataTableData();
foreach (var data in dataTable)
{
treeNodes.Add(new TreeNode() { Id = data.Id, Name = data.Name, ParentID = data.ParentID });
}
var root = BuildTree(treeNodes);
Console.ReadLine();
}
BuildTree()
分解
节点
列表中已包含与数据表中的数据对应的所有节点。BuildTree()
只会创建父子关系并填充每个对象的子对象列表
所以我遍历列表,看看列表中的其他元素应该是它的子元素。当您遍历列表时,您已经创建了所有的父子关系。最后,我选择根节点(ParentId为空的ParentId
)并返回它
编辑
这里有一个简单的方法来打印和验证您的树
static void PrintTree(TreeNode node, int indents)
{
for (int tab = 0; tab < indents; tab++)
{
Console.Write("\t");
}
Console.WriteLine("{0} - {1}", node.Id, node.Name);
if (node.Children != null && node.Children.Count > 0)
{
indents++;
foreach (var child in node.Children)
{
PrintTree(child, indents);
}
}
}
静态void打印树(TreeNode节点,int缩进)
{
对于(int-tab=0;tab0)
{
缩进++;
foreach(node.Children中的变量child)
{
打印树(子级,缩进);
}
}
}
我的输出如下所示:
| id | parentID | name |
|----------+----------+-------------|
|ABCD-12345| | Top |
|----------+----------+-------------|
|ABCD-23456|ABCD-12345| Middle |
|----------+----------+-------------|
|ABCD-34567|ABCD-23456| Bottom |
|----------+----------+-------------|
|ABCD-45678|ABCD-23456| Bottom |
首先,为了方便起见,我将修改TreeNode
类。这不是必须的,只是一个很好的选择。另外,我将假设在您的数据表中,您已经完成了错误检查,并且只有一个节点具有ParentId=“”
这就是您的Main()
的外观:
static void Main(string[] args)
{
var treeNodes = new List<TreeNode>();
var dataTable = GetDataTableData();
foreach (var data in dataTable)
{
treeNodes.Add(new TreeNode() { Id = data.Id, Name = data.Name, ParentID = data.ParentID });
}
var root = BuildTree(treeNodes);
Console.ReadLine();
}
BuildTree()
分解
节点
列表中已包含与数据表中的数据对应的所有节点。BuildTree()
只会创建父子关系并填充每个对象的子对象列表
所以我遍历列表,看看列表中的其他元素应该是它的子元素。当您遍历列表时,您已经创建了所有的父子关系。最后,我选择根节点(ParentId为空的ParentId
)并返回它
编辑
这里有一个简单的方法来打印和验证您的树
static void PrintTree(TreeNode node, int indents)
{
for (int tab = 0; tab < indents; tab++)
{
Console.Write("\t");
}
Console.WriteLine("{0} - {1}", node.Id, node.Name);
if (node.Children != null && node.Children.Count > 0)
{
indents++;
foreach (var child in node.Children)
{
PrintTree(child, indents);
}
}
}
静态void打印树(TreeNode节点,int缩进)
{
对于(int-tab=0;tab0)
{
缩进++;
foreach(node.Children中的变量child)
{
打印树(子级,缩进);
}
}
}
我的输出如下所示:
| id | parentID | name |
|----------+----------+-------------|
|ABCD-12345| | Top |
|----------+----------+-------------|
|ABCD-23456|ABCD-12345| Middle |
|----------+----------+-------------|
|ABCD-34567|ABCD-23456| Bottom |
|----------+----------+-------------|
|ABCD-45678|ABCD-23456| Bottom |
如果要构建类结构,则需要使用递归方法的类。如果它变得太大,不确定它的效率会有多高。从树的顶部执行该方法
public class TreeNode
{
public string id { get; set; }
public string name { get; set; }
public string parentID { get; set; }
public List<TreeNode> children { get; set; }
public TreeNode() {
children = new List<TreeNode>();
}
public TreeNode FindParentWithID(string ID)
{
TreeNode ParentWithID = null;
//check my parentID if i am the one being looked for then return
if (id == ID) return this;
//search children
foreach (TreeNode treeNode in children)
{
ParentWithID = treeNode.FindParentWithID(ID);
if (ParentWithID != null)
{
break;
}
}
return ParentWithID;
}
}
在本例中,topOne最终将成为treeNode6 name=“Middle”。如果要构建类结构,则需要使用递归方法的类。如果它变得太大,不确定它的效率会有多高。从树的顶部执行该方法
public class TreeNode
{
public string id { get; set; }
public string name { get; set; }
public string parentID { get; set; }
public List<TreeNode> children { get; set; }
public TreeNode() {
children = new List<TreeNode>();
}
public TreeNode FindParentWithID(string ID)
{
TreeNode ParentWithID = null;
//check my parentID if i am the one being looked for then return
if (id == ID) return this;
//search children
foreach (TreeNode treeNode in children)
{
ParentWithID = treeNode.FindParentWithID(ID);
if (ParentWithID != null)
{
break;
}
}
return ParentWithID;
}
}
在本例中,topOne最终将成为treeNode6 name=“Middle”。您的树列表是否总是只包含父级(因此始终是长度为1的列表)?还是我错了?我的意思是,这就是代码现在所做的,但这就是我在这篇文章中试图解决的问题。我不能完全确定我是否理解您的问题。问题是,鉴于您的DataTable
有四项,您是希望BuildTree()
返回一个包含四个TreeNode
元素且父子关系设置正确的列表,还是希望它只返回根TreeNode
对象,它的每个子元素都将包含定义树的其他元素?哦,我明白了-这两个元素中的后一个是我的目标。因此,使用示例DataTable
,我的根TreeNode
的ID为ABCD-12345。它将有一个ID为ABCD-23456的单个子TreeNode
对象的列表。该TreeNode
将依次具有一个包含两个子TreeNode
对象的列表,ID分别为ABCD-34567和ABCD-45678。问题是我不知道这些树的嵌套深度会有多深。你的树列表是否总是只包含父树(因此总是有一个长度为1的列表)?还是我错了?我的意思是,这就是代码现在所做的,但这就是我在这篇文章中试图解决的问题。我不能完全确定我是否理解您的问题。问题是,鉴于您的DataTable
有四项,您是希望BuildTree()
返回一个包含四个TreeNode
元素且父子关系设置正确的列表,还是希望它只返回根TreeNode
对象,它的每个子元素都将包含定义树的其他元素?哦,我明白了-这两个元素中的后一个是我的目标。因此,使用示例DataTable
,我的根TreeNode
的ID为ABCD-12345。它将有一个ID为ABCD-23456的单个子TreeNode
对象的列表。那棵树