I have a list of records containing Id, DateFrom, DateTo. For the sake of this question we can use this one:
List<(int, DateTime, DateTime)> data = new List<(int, DateTime, DateTime)>
{
(1, new DateTime(2012, 5, 16), new DateTime(2018, 1, 25)),
(2, new DateTime(2009, 1, 1), new DateTime(2011, 4, 27)),
(3, new DateTime(2014, 1, 1), new DateTime(2016, 4, 27)),
(4, new DateTime(2015, 1, 1), new DateTime(2015, 1, 3)),
};
In my real case the List could be a lot bigger, for now I assume that there is only one entry for a certain Id.
The task is to find the two records that has the longest time overlap and to return the ids and the number of days overlapped.
Which in this sample case means that these should be records 1 and 3, because 2 is not overlapping with anyone, and 4 overlaps for shorter time.
My implementation of this is the following:
public (int, int, int) GetLongestElapsedPeriod(List<(int, DateTime, DateTime)> periods)
{
int firstId = -1;
int secondId = -1;
int periodInDays = 0;
foreach (var period in periods)
{
var Id = period.Item1;
var dateFrom = period.Item2;
var dateTo = period.Item3;
for (int i = 0; i < periods.Count; i++)
{
if (Id != periods[i].Item1)
{
var tempId = periods[i].Item1;
var tempDateFrom = periods[i].Item2;
var tempDateTo = periods[i].Item3;
if (tempDateFrom < dateTo && tempDateTo > dateFrom)
{
DateTime commonStartingDate = tempDateFrom > dateFrom ? tempDateFrom : dateFrom;
DateTime commonEndDate = tempDateTo > dateTo ? dateTo : tempDateTo;
var elapsedPeriod = commonEndDate - commonStartingDate;
if ((int)elapsedPeriod.TotalDays > periodInDays)
{
periodInDays = (int)elapsedPeriod.TotalDays;
firstId = Id;
secondId = tempId;
}
}
}
}
}
return (firstId, secondId, periodInDays);
}
But I think this way is not very efficient and I'm looking for ideas to optimize this logic. Also, I suspect that this is variation of some more general algorithmic problem.
Item2perhaps? \$\endgroup\$