在列表中查找嵌套级别<>使用属性

时间:2017-02-06 17:32:19

标签: c# foreach nested

我尝试使用我从服务中接收的一些数据来构建树结构。不幸的是,我无法控制我收到的数据结构。该对象是这样构建的:

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
            }
      }
}

}

就像我说的,这个解决方案确实有效,但我真的觉得必须有一个更程序化,更清晰,更有效的方法来处理这个问题

2 个答案:

答案 0 :(得分:2)

开始

以下假设您有一个方法可以返回Modules的扁平列表。此外,这是未经测试的 - 可能是拼写错误或错误...大约在我开始为您提供Modules的分层列表的地方。请注意,我已将ParentChildren添加到您的Module课程中。

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);
        }
    }
}

你得到什么

这会让您获得原始列表,但每个Module可能有孩子,并且可能有父母。

你可能想要什么

您可能真正想要的只是顶级Modules的列表,并且您对该事物进行了数据绑定。这很简单,例如:

List<Module> topLevelModules = moduleList.Where(m => m.Parent == null).ToList();

答案 1 :(得分:0)

首先,我会将List<object>投射到List<Module>

List<Module> modules = moduleList.Cast<Module>();

然后我会创建一个字典,以便通过ModuleCode

轻松访问这些项目
Dictionary<string, Module> codeToModule = modules.ToDictionary(m => m.ModuleCode, m => m);

然后我会用一些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();

现在你有一个所有树节点的平面列表,每个节点都引用它的父节点(如果有的话)并且有一个子节点列表。
您现在可以选择根节点:

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));