【发布时间】:2016-03-10 15:57:38
【问题描述】:
我已经实现了如下层次接口
interface ITree<T>
{
// Incremential unique key
int Id { get; set; }
string Name { get; set; }
// Hierarchy classical pattern
T Parent { get; set; }
ICollection<T> Children { get; set; }
// Computed values
int Depth { get; }
// Hierarchy path with dotted notation (e.g.: 12.45.554.23,
// where each path segment is an Id)
string Path { get; set; }
}
class TreeItem : ITree<TreeItem>
{
public int Id { get; set; }
public string Name { get; set; }
public TreeItem Parent { get; set; }
public ICollection<TreeItem> Children { get; set; }
public string Path { get; set; }
public int Depth { get { return Path.Split('.').Length - 1; } }
}
这些项目是通过实体框架存储和检索的,因此我们可以假设所有的关系字段都不为空且一致:
-
Path和Depth始终是最新的 - 链接作品(例如:
item.Parent?.Parent?.Parent) - 遍历
Children字段也是递归的。 - 使用
Path和Depth是首选方法,因为它不需要计算关系字段。
考虑我有以下层次结构:
- A (Depth = 0)
-- B (Depth = 1)
-- C (Depth = 1)
- D (Depth = 0)
-- E (Depth = 1)
我所有的元素都在一个无序的平面数组中,比如说 [D,C,B,E,A]。 我想使用 Linq 表达式按以下方式对它们进行排序:
- 第一级 0,根据其名称字段
- 前一个的所有 1 级子级,按名称排序
- 第二级 0(仍根据其名称字段)
- 之前的所有 1 级孩子...
该示例针对 2 级深度给出,但我希望表达式遍历层次结构,无论其深度如何。
请注意,我的数据结构的级别和路径字段可用于实现此目的,因为每当添加、移动或删除项目时,树的所有路径都会重新构建,并且深度字段是通过简单的拆分计算的('.') 在路径上。
测试样本:
var A = new TreeItem { Id = 1, Name = "A", Path = "1" };
var B = new TreeItem { Id = 2, Name = "B", Path = "1.2", Parent = A };
var C = new TreeItem { Id = 3, Name = "C", Path = "1.3", Parent = A };
var D = new TreeItem { Id = 4, Name = "D", Path = "4" };
var E = new TreeItem { Id = 5, Name = "E", Path = "4.5", Parent = D };
// populate children for the example.
// My actual code is automatic thanks to EF Inverse Relationship.
A.Children = new List<TreeItem> { B, C };
D.Children = new List<TreeItem> { E };
var listToSortHierarchically = new List<TreeItem> { D, C, B, E, A };
// I want the result of the hierarchical sort to be A B C D E
【问题讨论】:
-
什么是
T?您能否提供一个示例实现。而且不应该至少限制为where T : ITree<T> -
我添加了一个示例实现。基本上,T 是一个 POCO 对象,Tree 接口确保它具有 Id、Name、Parent、Children、Depth 和 Path 字段的外观。
-
谢谢。它不是编译,但无论如何。约束怎么样?我的意思是,如果我有
ITree<TreeItem> node,我可以使用node.Parent.Parent等吗?没有约束,我需要强制转换吗? -
好的,快速编辑以获得可编译的模型并回答您的问题,但我将提供一个代码示例来设置层次结构。