Reputation: 378
I am iterating through a list and looking for objects that have the same value for one of their properties. I need an IEnumerable of the unique values of the properties that overlap.
This was my original nested loop solution.
List<Event> eventsWithDatetimeCollisions = new List<Event>();
for (int i = 0; i < eventList.Count; i++)
{
Event event1 = eventList[i];
for (int j = i + 1; j < eventList.Count; j++) // for each event after event1 in the list
{
Event event2 = eventList[j];
if (DateTime.Compare(event1.EventDateTime, event2.EventDateTime) == 0)
eventsWithDatetimeCollisions.Add(event1);
}
}
@NetMage pointed out a bug in my loop solution that if there are 3 events with the same time, the first will be added to the list twice and the second will be added once. A similar problem exists with my LINQ solution.
I came up with the following query that almost gives me the results I want but it has some duplicate values and I am wondering if it could be written better. I am manually checking that the events aren't the same, is there a way to avoid this? As I understand it, this query will compare every event to each event in the list including itself which results in a lot of extra comparisons.
var dateTimeCollisions = from event1 in eventList
from event2 in eventList
where event1 != event2 // I want to avoid this bit
&& DateTime.Compare(event1.EventDateTime, event2.EventDateTime) == 0
select event1;
This isn't something that needs to be optimized for speed, most of the time the list has less than 5 items in it and it's not getting executed regularly or at short intervals, I was just curious if there is a better way (more efficient, easier to read / write, etc).
Upvotes: 0
Views: 1450
Reputation: 752
GroupBy might be a better option here - a bit more memory but much lower complexity.
eventList.GroupBy(x => x.EventDateTime).Where(g => g.Count() > 1)
Each group's key is the collision datetime, and value is the events which collide on that time.
Adding .Select(g => g.Key)
will give you just the datetimes.
Upvotes: 5
Reputation: 26917
This will collect the first entry in eventList
that has an equal EventDateTime
later in the list.
var eventsWithDatetimeCollisions = eventList.GroupBy(e => e.EventDateTime)
.Where(eg => eg.Count() > 1)
.Select(eg => eg.First())
.ToList();
Upvotes: 1