Sort and group the list of objects by several properties
I have a complex sort / grouping that needs to be done on a list of objects.
Objects have three properties: Event name Start End
I am assigned the event name "EventName" and the start / end time for the specified event and populated with a List.
Now comes the tricky part.
Requirements: - the same EventName can have several records with different start and end times - events must be sorted by start time, with the earliest events first - events, if they have the same start time, then must be sorted by the shortest and longest times execution. - events are then grouped, so all events with the same name are listed in ascending order under the event name. - Events with different names but the same total early start time are sorted alphabetically.
For example:
List (0):
EventName: Test 2 Start: 10am End: 3pm
List (1):
EventName: Test 2 Start: 10am End: 11am
List (2):
EventName: Test 1 Start: 12pm End: 1pm
List (3):
EventName: Test 2 Start: 2pm End: 3pm
So when all is said and done, the list should be sorted like:
List (0):
EventName: Test 2 Start: 10am End: 11am
List (1):
EventName: Test 2 Start: 10am End: 3pm
List (2):
EventName: Test 2 Start: 2pm End: 3pm
List (3):
EventName: Test 1 Start: 12pm End: 1pm
I'm really not sure how to do this. I have this a lot that doesn't work:
theList.OrderBy(o => o.Start).ThenBy(o => o.End).ThenBy(o => o.EventName);
Any help would be appreciated.
EDIT To make it easier, let's say the time is converted to 24 hour time and stored as ints, how can I easily do this.
source to share
I believe I have it!
I just had to do some little tweaks to what I already had.
Here's the code that still works as I need it:
theList.GroupBy(o => o.EventName).Select(s => s.OrderBy(a => a.Start).ThenBy(a => a.End)).SelectMany(sm => sm).ToList();
In cases where all other offers fell, the EventNames grouping was grouped when sorted by start time.
_
source to share
Solution without 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;
});
Solution adapted from Sorting list by code, then by name . Unverified. Especially the return statement may need manipulation. Replace the event with whatever you are using as the List object.
source to share
You need to store Start
and End
in temporary variables without am and pm, and then perform a sort operation on these numbers Suppose that a class name that has these three properties Event
, then here is the linq operator
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 });
Edit
try changing the sequence OrderBy
to
.OrderBy(s => s.EventName)
.ThenBy(s => s.NumberStart)
.ThenBy(s => s.NumberEnd - s.NumberStart)
source to share