【问题标题】:C# LINQ select hierarchy from list where root has a certain property valueC# LINQ 从 root 具有特定属性值的列表中选择层次结构
【发布时间】:2016-08-06 18:58:05
【问题描述】:

我有一个具有以下属性的类:

  • int ID
  • 整数?家长 ID
  • 布尔?需求展示

我有一个这些对象的列表,该列表代表多个层次结构:ID 是键值,而 ParentID 充当外键。 NeedsShowing 仅在每个层次结构的根级别填充,这意味着它仅在 ParentID == null 时出现。

我需要完成的——最好使用最简单的 LINQ——只选择列表中的那些层次结构,其中NeedsShowing == true(基本上应用过滤器)。

列表中有大约 50,000 个对象,代表大约 13,000 个层次结构。

代码

Public Class FileHierarchy
{
  int ID { get; set; }
  int? ParentID { get; set; }
  bool? NeedsShowing { get; set; }
}

具有值的 FileHierarchy 类列表:

ID     ParentID       NeedsShowing
----------------------------------
1      null           true
2      1              null
3      1              null
4      2              null
5      null           false
6      5              null
7      6              null
8      null           true
9      8              null

这意味着我有三个层次结构,根节点 ID 为 1、5、8(其中parent ID == null)。我只想获取根 ID 为 1 和 8 的层次结构中的所有节点,因为根 ID 5 具有 NeedsShowing == false

【问题讨论】:

  • 您说“获取层次结构”是什么意思?您想要所有这些层次结构中所有节点的列表,根列表吗?
  • @Stephen:我试图获取 NeedsShowing == true 的对象列表,但它只返回每个层次结构的根对象。不应该在那里使用。不知何故,我需要从列表中构建层次结构,但我不知道如何。
  • Servy:我的意思是获取所有节点:根节点+层次树中根节点有NeedsShowing == true的所有子节点。
  • 我认为您应该为您的类添加代码,至少是它们的属性,以及您尝试对其运行查询的列表。

标签: c# linq


【解决方案1】:

试试这个

List<FileHierarchy> mylist = GetList();
var selected = mylist.Where(s => s.NeedsShowing.HasValue && s.NeedsShowing.Value);
var children = mylist.Where(c => c.ParentID.HasValue && selected.Select(s => s.ID).Contains(c.ParentID.Value));
var unselected = mylist.Except(selected);
while (children.Any())
{
    unselected = unselected.Except(children);
    var childChild = unselected.Where(c => c.ParentID.HasValue && children.Select(s => s.ID).Contains(c.ParentID.Value));
    selected = selected.Union(children);
    children = childChild;
}

【讨论】:

  • 谢谢,但这只会显示根节点,而不是根下的整个层次结构。
  • 但是您没有解释层次结构与根节点的关系。它与ParentID有关吗?如果是这样,当 NeedsShowing 为真时,ParentID 为空是不可能的,因此您无法从中获取任何层次结构
  • 对不起,如果我不清楚。 ID 是每个节点的唯一标识符。 ParentID 包含层次结构中直接位于其上方的节点的 ID。 ParentID只有在我们谈到根节点时才为null,否则它包含上面节点的ID。
  • 我编辑了我的答案,为您提供根节点 + 根节点下一级的节点 - 您的层次结构是否包含比这更深的级别?
  • 是的,它们可以在我们的应用程序中进入任何深度(没有限制,但我已经看到了 20 个深度层次结构)。
【解决方案2】:

我认为这更具可读性和可调试性,您可以根据需要调整结果。也许更快(没有直接比较)。除了像@Zrethreal's answer那样递归或超迭代之外,真的没有办法做到这一点。我更喜欢递归。

    private static void Main(string[] args)
    {
        var files = GetFiles();
        var searchableFiles = files.Except(files.Where(f1 => f1.NeedsShowing ?? false && f1.ParentID == null)).ToList()
        var whereNeedShowing = (from f in files
                                where f.NeedsShowing ?? false
                                select new {Root = f, Descendants = FindDescendants(f.ID, searchableFiles) }).ToList();
        Debug.Assert(whereNeedShowing.Count == 2);
    }

    static List<FileHierarchy> FindDescendants(int? parentId, IEnumerable<FileHierarchy> files)
    {
        var children = files.Where(f => f.ParentID == parentId).ToList();
        foreach(var child in children.ToList())
        {
            var newChildren = FindDescendants(child.ID, files.Except(children));
            children.AddRange(newChildren);
        }
        return children;
    }

    static List<FileHierarchy> GetFiles()
    {
        var result = new List<FileHierarchy>();
        for (int i = 1; i <= 9; i++)
        {
            var file = new FileHierarchy()
            {
                ID = i, 
                ParentID = i == 1 || i == 5 || i == 8 ? (int?) null : i - 1, 
                NeedsShowing = i == 1 || i == 8 ? true : (i == 5 ? false : (bool?) null)
            };
            result.Add(file);
            if (i == 3)
            {
                file.ParentID = 1;
            }
            else if (i == 4)
            {
                file.ParentID = 2;
            }
        }
        return result;
    }
}

public class FileHierarchy
{
    public int ID { get; set; }
    public int? ParentID { get; set; }
    public bool? NeedsShowing { get; set; }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多