首先让我说明一下我的目标与实现目标之间的关系
在控制器中,我以非常随机的未排序方式将所有类别分成单个通用列表
var categories = new List<Category>(this.categoryService.GetCategories())
每个类别都有4个属性,重要的是 ID , ParentCategoryId , SortOrder ,文字
SortOrder 必须仅应用于层次结构中同级别的同级,并且子级必须始终位于其父级之下。 文字必须通过预先添加&#34; ..&#34;对于每个深度级别。
我希望在考虑到性能的情况下正确完成此操作,不要多次递归遍历大量列表。
感谢您的任何意见。
答案 0 :(得分:7)
这可能不是最性能代码,但应该适用于 OP 的问题。
由于 OP 没有明确定义有问题的数据结构(模型),我将假设它是这样的:
public class Category {
public int Id { get; set; }
public int ParentCategoryId { get; set; }
public int SortOrder { get; set; }
public string Text { get; set; }
}
要将类别列表(List<Category>
)排序为多级别类别,我们需要一个树状结构来保存数据。
首先,我会使用Category
等新属性扩展模型(Level
类)(以指示级别深度),Children
(以保存子/子{ {1}})和Category
(根据其级别显示类别文本):
DisplayText
注意:取决于您的偏好,您可以直接更改public class CategoryNode : Category {
public CategoryNode(Category category) {
Id = category.Id;
ParentCategoryId = category.ParentCategoryId;
SortOrder = category.SortOrder;
Text = category.Text;
}
public CategoryTree Children { get; set; }
public int Level { get; set;}
public string DisplayText {
get {
// OP wants two-dots prefix per level
return string.Concat(new string('.', Level*2), Text);
}
}
}
类,而不是将其子类化为Category
。
接下来,我将定义一个类来包装名为CategoryNode
的{{1}}集合,它是CategoryNode
的简单包装器,它公开CategoryTree
interace。我还在List<CategoryNode>
中添加了一个IEnumerable
方法,它将树状结构展平为一个列表。此方法可以方便地将数据绑定到单个列表(非分层)控件,例如Flatten()
或CategoryTree
。最后,我还添加了一个名为DropDownList
的静态创建方法,以根据给定的ListBox
列表创建Create()
的实例:
CatogoryTree
注意:再次,可以说,您可以直接使用Category
,提取方法,并省去自己在这里创建新类的麻烦。你的电话。
有了所有部分,我现在可以使用以下代码将public class CategoryTree : IEnumerable<CategoryNode> {
private List<CategoryNode> innerList = new List<CategoryNode>();
public CategoryTree(IEnumerable<CategoryNode> nodes) {
innerList = new List<CategoryNode>(nodes);
}
public IEnumerator<CategoryNode> GetEnumerator()
{
return innerList.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public IEnumerable<CategoryNode> Flatten() {
foreach(var category in innerList.OrderBy(o => o.SortOrder)) {
yield return category;
if (category.Children != null) {
foreach(var child in category.Children.Flatten()) {
yield return child;
}
}
}
}
public static CategoryTree Create(
IEnumerable<Category> categories,
Func<Category, bool> parentPredicate,
int level = 0)
{
var nodes = categories
.Where(parentPredicate)
.OrderBy(o => o.SortOrder)
.Select(item => new CategoryNode(item) {
Level = level,
Children = Create(categories, o => o.ParentCategoryId == item.Id, level + 1)
});
return new CategoryTree(nodes);
}
}
(List<CategoryNode>
)列表转换为Category
的多级列表,并展平该列表以将其绑定进入List<Category>
:
Category
演示(使用DropDownList
):https://ideone.com/ejOfrr
答案 1 :(得分:0)
您是否尝试过实施字典结构?
如:
Dictionary<Categories, List<T>> dictionary = new Dictionary<Categories, List<T>>();
这可能符合您的要求。
此外,如果您想要一个已排序的类别结构,您可以实现一个SortedDictionary,其中Category为Key&amp;相应的列表作为值。