2

I have a SortedDictionary of DateTime and double _historicalValues, and a method HistoricalValue which is passed a DateTime date. HistoricalValue must return the corresponding double for the DateTime in _historicalValues that is closest to date. Is there a nice way in which I can leverage a SortedDictionary in order to find the closest DateTime?

I think there is a better way to approach this task as my approach is something that doesn't leverage a SortedDictionary at all, and tediously has to iterate over the whole collection to evaluate the date differences first.

private readonly SortedDictionary<DateTime, double> _historicalValues;    

public double HistoricalValue(DateTime date)
{
    if (_historicalValues.ContainsKey(date))
        return _historicalValues[date];

    var closestDate = _historicalValues.Keys.OrderBy(
          t => Math.Abs((t - date).Ticks)).First();
    return _historicalValues[closestDate];
}
Eric Hansen
  • 1,609
  • 11
  • 33
  • How far apart are these historical values? Could be worth chopping the whole thing up by year, then month, then week. Gives you a much smaller set to work with and could speed things up. – Trev Davies Mar 31 '16 at 07:28
  • You don't need a sorted dictionary, because you don't use the actual pairs and just the result. A regular dictionary would work fine in this case and if you want to have it store less since store the pair like `uint,double` or `long,double` and then simply convert the datetime to the corresponding datatype ex. with `date.ToBinary()`. – Bauss Mar 31 '16 at 07:30
  • If it's a short list of historical dates, just iterate on them, if you want to optimize for large sets, you can have a sorted list/array and perform a binary search with a variation. Alternatively you can probably create (or find) a heap implementation. Your find should perform an insert (but not insert the item) and find the two neighboring values. – o_weisman Mar 31 '16 at 07:30
  • @Bauss That's precisely why I'm asking if there is any way I can leverage a SortedDictionary. – Eric Hansen Mar 31 '16 at 07:31
  • 1
    See here: http://stackoverflow.com/questions/12412869/efficiently-find-nearest-dictionary-key. Note that you should bother only if your dictionary is large.Otherwise just iterate over (already sorted) array of your keys and compare with target date. – Evk Mar 31 '16 at 07:35

1 Answers1

2

I would use the MinBy mentioned in this answer: enter link description here

And then use it like this:

return _historicalValues.MinBy(kvp => Math.Abs((kvp.Key - date).Ticks)).Value;
Community
  • 1
  • 1
R00st3r
  • 859
  • 1
  • 8
  • 27
  • Thank you very much R00st3r, I had a similar problem, and this really helped a lot! – Erik Jul 07 '16 at 08:22