Reputation: 2465
I have a calendar of events. I use the following LINQ statement to load the events to display in a calendar:
var events = CalendarItems?.GroupBy(e => e.StartDate);
It results in a GroupedEnumerable with key/values like this:
Key = 6/26/2019, Value = CalendarItem
Key = 7/10/2019, Value = CalendarItem
Key = 7/18/2019, Value = CalendarItem
Some CalendarItems have "EndDate" and if it does, I would like each date in the range of StartDate to EndDate to also be included in the result set. So if the 7/18/2019 CalendarItem had an EndDate of 7/20/2019, then my result set would also include these 2 items:
Key = 7/19/2019, Value = CalendarItem
Key = 7/20/2019, Value = CalendarItem
I have no idea how I would modify my LINQ statement. Any recommendations?
Thanks!
So, if I had these 2 CalendarItems:
StartDate = 7/8/2019, EndDate = null
StartDate = 7/18/2019, EndDate = 7/20/2019
Then my result should be:
Key = 7/8/2019, Value = CalendarItem
Key = 7/18/2019, Value = CalendarItem
Key = 7/19/2019, Value = CalendarItem
Key = 7/20/2019, Value = CalendarItem
Upvotes: 0
Views: 74
Reputation: 7162
class Item
{
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
}
var items = new List<Item>
{
new Item {StartDate = new DateTime(2019, 2, 22)},
new Item {StartDate = new DateTime(2019, 3, 12 )},
new Item {StartDate = new DateTime(2019, 4, 15), EndDate = new DateTime(2019, 4, 25) },
new Item {StartDate = new DateTime(2019, 2, 15), EndDate = new DateTime(2019, 2, 17) },
new Item {StartDate = new DateTime(2019, 2, 23)},
new Item {StartDate = new DateTime(2019, 2, 7)},
};
var x = items.Select(i => (i.StartDate, diff: Enumerable.Range(0, ((i.EndDate == null ? i.StartDate : i.EndDate).Value - i.StartDate).Days + 1)))
.Select(x => x.diff.Select(z => x.StartDate.AddDays(z)));
var days = new List<DateTime>();
x.ToList().ForEach(dates => days.AddRange(dates));
// Output:
days.OrderBy(i => i).ToList().ForEach(d => Console.WriteLine(d.ToShortDateString()));
/*
Output:
07.02.2019
15.02.2019
16.02.2019
17.02.2019
22.02.2019
23.02.2019
12.03.2019
15.04.2019
16.04.2019
17.04.2019
18.04.2019
19.04.2019
20.04.2019
21.04.2019
22.04.2019
23.04.2019
24.04.2019
25.04.2019
*/
Upvotes: 0
Reputation: 617
Try this:
var events = CalendarItems?.Where(x => x.EndDate.HasValue && x.StartDate < x.EndDate).GroupBy(e => e.StartDate);
(For the first check you could also do x.EndDate != null
)
The biggest thing to note is just the .Where()
clause. You could perform this when looping through the groups as well. So if you need to do the checks after the grouping, you could use this alternatively:
var events = CalendarItems?.GroupBy(e => e.StartDate);
foreach(var event in events)
{
var validEvent = event.Where(x => x.EndDate.HasValue && x.StartDate < x.EndDate);
}
Functionally they're the same, but if for whatever reason you need to process the other dates, that foreach()
will let you pick through what you need on a group by group basis.
Upvotes: 1