我有一个具有以下属性的类:
我有一个这些对象的列表,该列表代表多个层次结构: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
。
答案 0 :(得分: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;
}
答案 1 :(得分:0)
我认为这更具可读性和可调性性,如果您愿意,可以调整结果。也许更快(避难所直接比较)。除了@ Zrethreal的答案之外,除了递归或超迭代之外,真的没办法做到这一点。我更喜欢递归。
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; }
}