C#使用LINQ按日期、ID及Guid类型父ID实现层级列表排序
层级排序实现方案
需求说明
待排序列表实体包含三个字段:
Id:Guid类型,条目唯一标识ParentId:可空Guid类型,关联父条目的Id,根节点该值为nullDate:DateTime类型,条目日期
排序规则:
- 根节点按日期倒序,日期最新的根节点排在最前
- 所有子节点必须紧跟在所属父节点之后
- 同一父节点下的子节点按日期排序
原有链式OrderBy+ThenBy的写法属于扁平排序,仅能根据单条数据自身属性计算排序权重,无法让子节点自动跟随父节点的排序位置,因此无法实现层级跟随效果。
涉及的实体类定义:
public class MyModel { public Guid Id { get; set; } public Guid? ParentId { get; set; } public DateTime Date { get; set; } }
实现代码
采用深度优先遍历的方式构建有序序列:先对根节点按规则排序,再逐个将每个节点下排序后的子节点追加到结果中,天然满足父节点在前、子节点紧随的要求,且支持任意深度的树形结构。
public static List<MyModel> SortHierarchicalList(List<MyModel> sourceList) { // 按父ID分组构建快速查找索引,避免每次遍历全表找子节点 var childrenGroup = sourceList.ToLookup(item => item.ParentId); var sortedResult = new List<MyModel>(sourceList.Count); // 递归追加当前节点下的所有子节点 void AppendChildren(MyModel currentParent) { // 同层级子节点按日期正序排列,需要倒序可替换为OrderByDescending var sortedChildren = childrenGroup[currentParent.Id].OrderBy(child => child.Date); foreach (var child in sortedChildren) { sortedResult.Add(child); AppendChildren(child); } } // 第一步:所有根节点按日期倒序排列 var sortedRootNodes = childrenGroup[null].OrderByDescending(root => root.Date); foreach (var root in sortedRootNodes) { sortedResult.Add(root); AppendChildren(root); } return sortedResult; }
调用方式
// 直接传入原始列表即可得到符合要求的排序结果 var sortedItems = SortHierarchicalList(myList);
验证说明
使用提供的测试数据集运行后,输出顺序完全符合预期:
- 日期为2022-05-16的根节点,紧随其日期为2022-05-20的子节点
- 日期为2022-05-13的根节点,紧随其日期为2022-05-17、2022-05-18的两个子节点
- 剩余根节点按日期倒序依次排列:2019-05-20、2018-01-10、2011-06-05、2007-12-10,无子节点则直接排列根节点本身。
该实现时间复杂度为O(n),数据量大时性能表现优异,排序规则可根据业务需求灵活调整根节点、子节点的排序字段和升降序逻辑。
内容的提问来源于stack exchange,提问作者Nejox
相关产品推荐
相关产品推荐

