c# - 排序列表,其中前任和后继定义排序
问题描述
我需要对 LineItems 列表进行排序,其中在每个 LineItem 中定义了一个前任和后继。
LineItem{
public int Id {get;set;}
public int? PredecessorId {get;set;}
public int? SuccessorId {get;set;}
}
第一个 LineItem 没有 PredecessorId,最后一个 LineItem 没有 SuccessorId。
我以为我可以只实现 IComparable 但是对于 2 个项目,在这种情况下它不可能计算排序。
我将如何对列表进行排序List<LineItem>
?
编辑
这是一个示例
List<LineItem> lineItems = new List<LineItem>{
new LineItem{ Id = 1, PredecessorId = 2, SuccessorId = 103},
new LineItem{ Id = 2, PredecessorId = null, SuccessorId = 1},
new LineItem{ Id = 103, PredecessorId = 1, SuccessorId = 5},
new LineItem{ Id = 4, PredecessorId = 5, SuccessorId = null},
new LineItem{ Id = 5, PredecessorId = 103, SuccessorId = 4},
};
预期的排序是:
2,1,103,5,4
解决方案
您可以在子句中排除具有null
值的两项where
,对其余项进行排序,将它们添加到排序列表中:
var sortedList = lineItems
.Where(x => x.PredecessorId != null && x.SuccessorId != null)
.OrderBy(x => x.Id)
.Prepend(lineItems.FirstOrDefault(x => x.PredecessorId == null))
.Append(lineItems.FirstOrDefault(x => x.SuccessorId == null))
.Where(x => x != null).ToList();
Console.WriteLine(string.Join(", ", sortedList.Select(x => x.Id)));
输出是:
2, 1, 3, 5, 4
如果它可能有一个包含两个以上具有null
值属性的项目的列表,例如:
var lineItems = new List<LineItem>
{
new LineItem{ Id = 1, PredecessorId = 2, SuccessorId = 3},
new LineItem{ Id = 2, PredecessorId = null, SuccessorId = 1},
new LineItem{ Id = 3, PredecessorId = 1, SuccessorId = 5},
new LineItem{ Id = 4, PredecessorId = 5, SuccessorId = null},
new LineItem{ Id = 5, PredecessorId = 3, SuccessorId = 4},
new LineItem{ Id = 6, PredecessorId = null, SuccessorId = 6},
new LineItem{ Id = 7, PredecessorId = 7, SuccessorId = null},
};
然后你可以这样做:
var sortedList = lineItems
.Where(x => x.PredecessorId != null && x.SuccessorId != null)
.OrderBy(x => x.Id)
.ToList();
sortedList.InsertRange(0, lineItems
.Where(x => x.PredecessorId == null).OrderBy(x => x.Id));
sortedList.AddRange(lineItems
.Where(x => x.SuccessorId == null).OrderBy(x => x.Id));
Console.WriteLine(string.Join(", ", sortedList.Select(x => x.Id)));
或者,创建Prepend
和Append
扩展采用IEnumerable<LineItem>
以下类型的方法:
static class Extensions
{
public static IEnumerable<T> Prepend<T>(
this List<T> source, IEnumerable<T> element)
{
source.InsertRange(0, element);
return source;
}
public static IEnumerable<T> Append<T>(
this List<T> source, IEnumerable<T> element)
{
source.AddRange(element);
return source;
}
}
然后得到排序列表如下:
var sortedList = lineItems
.Where(x => x.PredecessorId != null && x.SuccessorId != null)
.OrderBy(x => x.Id).ToList()
.Prepend(lineItems.Where(x => x.PredecessorId is null)
.OrderBy(x => x.Id)).ToList()
.Append(lineItems.Where(x => x.SuccessorId is null)
.OrderBy(x => x.Id)).ToList();
Console.WriteLine(string.Join(", ", sortedList.Select(x => x.Id)));
两个输出都是:
2, 6, 1, 3, 5, 4, 7
为编辑而编辑
仅使用新的扩展方法Append
:
var sortedList = lineItems
.Where(x => x.PredecessorId is null &&
x.SuccessorId != null).ToList()
.Append(lineItems.Where(x => x.PredecessorId != null &&
x.SuccessorId != null)).ToList()
.Append(lineItems.Where(x => x.PredecessorId != null &&
x.SuccessorId is null)).ToList();
Console.WriteLine(string.Join(", ", sortedList.Select(x => x.Id)));
结果:
2, 1, 103, 5, 4
推荐阅读
- javascript - 布局中的 Xaxis 和 yaxis 自定义属性未针对 plotly 3d 网格图显示
- android - Duplicate Classes in AWS API and Appsync Serivces for Android
- c# - Linq 查询未选择字段列表
- ios - 使用外部 IDE 时模拟器上的 iOS pod 相关构建错误
- javascript - 在 JavaScript 中提交时值的长度验证错误
- powershell - PowerShell 作为 EXE 调用 AWS CLI 但不向窗口显示任何内容
- prometheus - 如何在 Grafana 中监控 Docker 所有容器 CPU/磁盘/内存的使用情况
- ios - IOS中的推荐系统?
- azure-synapse - 如何计算 Azure Synapse 管道成本
- javascript - 使用 ngIf 的角度隐藏元素需要更长的时间