Я реализовал следующий интерфейс иерархии
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; } }
}
Эти элементы хранятся и извлекаются через Entity Framework, поэтому мы можем предположить, что все поля отношения не являются нулевыми и непротиворечивыми:
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 уровня предыдущего...
Пример дан для двух уровней глубины, но я хотел бы, чтобы выражение проходило через иерархию независимо от ее глубины.
Обратите внимание, что для этого можно использовать поля уровня и пути моей структуры данных, так как все пути дерева перестраиваются всякий раз, когда элемент добавляется, перемещается или удаляется, а поле Глубина вычисляется с помощью простой функции Split('. ') на пути.
Проба :
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>
- person Ivan Stoev   schedule 10.03.2016ITree<TreeItem> node
, могу ли я использоватьnode.Parent.Parent
и т. д.? Без ограничения, мне нужно бросить? - person Ivan Stoev   schedule 10.03.2016