Reputation: 439
I have a dictionary where the key is a DateTime. I need to find the 2 entries in the dictionary that are closest to a given datetime.
So, I have
Dictionary<DateTime, double> columnInfos = new Dictionary<DateTime, double>();
foreach (var activity in activities)
{
DateTime activityDate = activity.ActivityDateTime;
// Get the 2 entries in the columnInfos dict that activityDate falls between
}
I was going to loop through the dictionary, but is that really the best way?> Anyone have a better solution?
Thanks
Upvotes: 0
Views: 909
Reputation: 733
This should work. index-1
and index+1
will be the position in the list of the dates immediately less than and greater than the date in question.
SortedDictionary<DateTime, double> columnInfos = new SortedDictionary<DateTime, double>();
List<KeyValuePair<DateTime, double>> columnInfosList = columnInfos.ToList();
foreach (var activity in activities)
{
DateTime activityDate = activity.ActivityDateTime;
for (int index = 1; index < columnInfosList.Count(); index++)
{
if (columnInfosList[index-1].Key < activityDate && columnInfosList[index+1].Key > activityDate)
{
// do something with columnInfos[index-1] and columnInfos[index+1] then break so you stop searching
}
}
}
Upvotes: 1
Reputation: 48686
If you can change your Dictionary<T, T>
to a SortedDictionary<T, T>
, you can write a function like this:
private List<DateTime> FallBetween(SortedDictionary<DateTime, double> columns, DateTime activityDate)
{
var keys = new List<DateTime>(columns.Keys);
int index = ~(keys.BinarySearch(activityDate));
var dates = new List<DateTime>();
try
{
dates.Add(keys[index]);
} catch { }
try
{
dates.Add(keys[index - 1]);
} catch { }
return dates;
}
And call it like this:
SortedDictionary<DateTime, double> columnInfos = new SortedDictionary<DateTime, double>();
columnInfos.Add(DateTime.Now, 1);
columnInfos.Add(DateTime.Now.AddDays(-2), 2);
columnInfos.Add(DateTime.Now.AddDays(-4), 3);
columnInfos.Add(DateTime.Now.AddDays(2), 4);
columnInfos.Add(DateTime.Now.AddDays(4), 5);
// dates will return a list containing two dates.
// Now - 2 days and Now - 4 days.
var dates = FallBetween(columnInfos, DateTime.Now.AddDays(-3));
// date will return a list containing only one date
// because there is only one nearing neighbor.
var date = FallBetween(columnInfos, DateTime.Now.AddDays(30));
Upvotes: 1