按多个属性对对象列表进行排序和分组
本文关键字:排序 列表 属性 对象 | 更新日期: 2023-09-27 18:25:07
我有一个复杂的排序/分组,需要使用对象列表来执行。
这些对象有三个特性:事件名称开始结束
我会得到一个事件的名称"EventName"和该事件的开始/结束时间,并填充一个列表。
现在是困难的部分。
要求是:-同一EventName可以有多个开始/结束时间不同的条目-事件将按开始时间排序,最早的事件将首先发生-如果事件的开始时间相同,则应按最短到最长的运行时间进行排序。-然后对事件进行分组,因此所有具有相同名称的事件都以升序列在事件名称下。-具有不同名称但总体最早开始时间相同的事件将按字母顺序排序。
例如:
列表(0):
事件名称:测试2开始时间:上午10点结束:下午3点
列表(1):
事件名称:测试2开始时间:上午10点结束:上午11点
列表(2):
事件名称:测试1开始时间:中午12点结束:下午1点
列表(3):
事件名称:测试2开始时间:下午2点结束:下午3点
因此,当一切都说了算,列表需要排序为:
列表(0):
事件名称:测试2开始时间:上午10点结束:上午11点
列表(1):
事件名称:测试2开始时间:上午10点结束:下午3点
列表(2):
事件名称:测试2开始时间:下午2点结束:下午3点
列表(3):
事件名称:测试1开始时间:中午12点结束:下午1点
我真的不知道该怎么做。我有这么多不起作用:
theList.OrderBy(o => o.Start).ThenBy(o => o.End).ThenBy(o => o.EventName);
如有任何帮助,我们将不胜感激。
编辑为了更容易,假设时间转换为24小时时间,并存储为int,因为我可以很容易地做到这一点。
我相信我有它!
只是对我已经有的东西做了一些小调整。
这是迄今为止我需要的代码:
theList.GroupBy(o => o.EventName).Select(s => s.OrderBy(a => a.Start).ThenBy(a => a.End)).SelectMany(sm => sm).ToList();
所有其他建议的失败之处在于,在按开始时间排序时,将EventNames分组在一起。
_
没有Linq:的解决方案
theList.Sort(delegate(Event p1, Event p2)
{
var byStart = p1.Start.CompareTo(p2.Start);
var byEnd = p1.End.CompareTo(p2.End);
var byEventName = p1.EventName.CompareTo(p2.EventName);
return byStart == 0 ? byEnd == 0 ? byEventName : byEnd : byStart;
});
解决方案改编自按代码排序列表,然后按名称排序。未测试。特别是return语句可能需要一些操作。将Event替换为用作List对象的任何对象。
您需要将Start
和End
存储到没有am和pm的临时变量中,然后对这些数字执行排序操作假设具有这三个属性的类名是Event
,那么这里是linq语句
list.Select(s => new
{
EventName = s.EventName,
Start = s.Start,
End = s.End,
// getting number without am/pm and where it is pm adding 12
NumberStart = s.Start.EndsWith("pm") ?
12 + Convert.ToInt32(s.Start.Trim('m').TrimEnd('p')) :
Convert.ToInt32(s.Start.Trim('m').TrimEnd('a')),
NumberEnd = s.End.EndsWith("pm") ?
12 + Convert.ToInt32(s.End.Trim('m').TrimEnd('p')) :
Convert.ToInt32(s.End.Trim('m').TrimEnd('a'))
}).OrderBy(s => s.NumberStart)
.ThenBy(s => s.NumberEnd - s.NumberStart)
.ThenBy(s => s.EventName)
.Select(s => new Event { EventName = s.EventName, Start = s.Start, End = s.End });
编辑
尝试将OrderBy
序列更改为
.OrderBy(s => s.EventName)
.ThenBy(s => s.NumberStart)
.ThenBy(s => s.NumberEnd - s.NumberStart)