C# 在列表中查找嵌套级别<&燃气轮机;使用属性
我试图用从服务接收到的一些数据构建一个树结构。不幸的是,我无法控制所接收数据的结构。对象的构建方式如下所示:C# 在列表中查找嵌套级别<&燃气轮机;使用属性,c#,foreach,nested,C#,Foreach,Nested,我试图用从服务接收到的一些数据构建一个树结构。不幸的是,我无法控制所接收数据的结构。对象的构建方式如下所示: class Module { public string ModuleCode {get;set;} public string ParentCode {get;set;} } 基本上,我得到了大约200个这样的对象的列表,我需要找到一种方法来对它们进行排序和排列,这样孩子们才能正确地与他们的父母联系起来 我现在有一个工作方法,就是使用foreach循环,但是它很
class Module
{
public string ModuleCode {get;set;}
public string ParentCode {get;set;}
}
基本上,我得到了大约200个这样的对象的列表,我需要找到一种方法来对它们进行排序和排列,这样孩子们才能正确地与他们的父母联系起来
我现在有一个工作方法,就是使用foreach循环,但是它很难看,并且只限于我硬编码的foreach循环的数量。我想要更有活力的东西
foreach (var module in moduleList.Where(x => string.IsNullOrWhiteSpace(x.ParentCode)))
{
//Module Level 1 -- Only uppermost parent modules here
moduleLevel = 1;
_highestModuleLevel = _highestModuleLevel < moduleLevel ? moduleLevel : _highestModuleLevel;
foreach (var module2 in moduleList.Where(x => x.ParentCode == module.ModuleCode))
{
//Module Level 2 -- 1st children modules
moduleLevel = 2;
_highestModuleLevel = _highestModuleLevel < moduleLevel ? moduleLevel : _highestModuleLevel;
foreach (var module2 in moduleList.Where(x => x.ParentCode == module1.ModuleCode))
{
//Module Level -- children of the 2nd level modules
moduleLevel = 3;
_highestModuleLevel = _highestModuleLevel < moduleLevel ? moduleLevel : _highestModuleLevel;
//Goes on for however many foreaches I can nest
}
}
}
foreach(moduleList.Where(x=>string.IsNullOrWhiteSpace(x.ParentCode))中的var模块)
{
//模块级别1--此处仅限最上面的父模块
moduleLevel=1;
_highestModuleLevel=_highestModuleLevelx.ParentCode==module.ModuleCode)中的变量module2)
{
//模块级别2——第一个子模块
moduleLevel=2;
_highestModuleLevel=_highestModuleLevelx.ParentCode==module1.ModuleCode)中的变量module2)
{
//模块级——第二级模块的子级
moduleLevel=3;
_highestModuleLevel=_highestModuleLevel
}
正如我所说,这个解决方案确实有效,但我真的觉得必须有一种更具程序性、更干净、更高效的方法来处理这个问题 下面假设您有一个方法,可以返回一个扁平的
模块列表
。此外,这是未经测试-可能是打字错误或错误。。。就在这里,我将开始为您提供一个模块的分层列表
。请注意,我在您的模块
类中添加了父类
和子类
class Module
{
public Module()
{
this.Children = new List<Module>();
}
public string ModuleCode {get; set;}
public string ParentCode {get; set;}
public Module Parent {get; set;}
public List<Module> Children {get; private set;}
}
static void main()
{
List<Module> moduleList = GetFlattenedModules();
IDictionary<string, Module> moduleCodeToModule =
moduleList.ToDictionary(m => m.ModuleCode);
foreach (Module module in moduleList)
{
if (module.ParentCode != null)
{
module.Parent = moduleCodeToModule[module.ParentCode];
module.Parent.Children.Add(module);
}
}
}
首先,我会将
列表
转换为列表
:
然后我将用一些TreeNode
对象创建一个树:
public class TreeNode
{
public Module Module { get; set; }
public Module Parent { get; set; }
public List<Module> Children { get; set; }
}
List<TreeNode> flatNodes = modules.Select(m => new TreeNode
{
Module = m,
Parent = m.ParentCode == null ? null : codeToModule[m.ParentCode],
Children = modules.Where(cm => cm.ParentCode == m.ModuleCode).ToList();
}).ToList();
在你的树的根上是什么?@DavidG,在根上,我按ParentCode为null的模块(x=>string.IsNullOrWhiteSpace(x.ParentCode))进行过滤,目标是什么?我看不出你把物品放在树上的什么地方…@RenéVogt,最终目标是用这些未分类的物品制作菜单。我需要为每个模块创建一个父/子关系,这样我就可以构建菜单,我没有为了简洁而显示它,但实际上我正在使用Razor为每个级别编写html。如果说得更清楚的话,我也可以把它包括在内,我只是觉得没必要,你有没有试过递归地做这个?这将解决n个嵌套对象的问题。顺便使用冲突的
m
lambda变量,然后使用它们比较m.ParentCode==m.ModuleCode
@MobigItal谢谢,修复了它。这就是我在离开办公室前匆匆忙忙地从头顶写东西时所发生的情况……同样不幸的是,这种结构没有利用模块中的字典
。其中(…)
区域,如果有很多模块,可能会变得非常慢。只是说说而已。另一个解决方案是,模块查找其父级并将其作为子级添加,这样效果更好—包括优化。我唯一的保留是,您正在合并原始模块
类和新的树节点类
类的目的。如果您有一个单独的TreeNode
类,那么对于请求者来说它会更干净。你永远不知道他们的输入类的起源是什么,他们可能不想从中派生,等等@Mobigital-true-很容易补救。我只是想给OP一个简单的起点。感谢您完成了从孩子到家长的查找,并在树重建中使用了字典@Mobigital-只是注意那个大O:)
List<Module> modules = moduleList.Cast<Module>();
Dictionary<string, Module> codeToModule = modules.ToDictionary(m => m.ModuleCode, m => m);
public class TreeNode
{
public Module Module { get; set; }
public Module Parent { get; set; }
public List<Module> Children { get; set; }
}
List<TreeNode> flatNodes = modules.Select(m => new TreeNode
{
Module = m,
Parent = m.ParentCode == null ? null : codeToModule[m.ParentCode],
Children = modules.Where(cm => cm.ParentCode == m.ModuleCode).ToList();
}).ToList();
List<TreeNode> rootNodes = flatNodes.Where(node => node.Parent == null).ToList();
public int GetDepth(TreeNode current, int depth)
{
return current.Children.Max(child => GetDepth(child, depth + 1));
}
int depth = rootNodes.Max(node => GetDepth(node, 0));