There is an array of dates, each date is assigned a specific parameter value. The user enters the date and it is necessary to determine the value of the parameter, the date of which is closest to the entered date. The only thing that comes to mind is to use an array of tuples List<Tuple<T1, T2>> in which to store the parameter and the difference between dates (the date of the parameter and the entered date) and then sort and take the first value. Perhaps there is a more beautiful way? Thank.
|
3 answers
As you rightly noted, sorting is not needed. Faster will run through all the elements, on the move calculating the closest. Well, do not forget to bring the dates to UTC, for example, if you have them from different belts.
var data = new Dictionary<DateTime, int>() { { DateTime.Now.AddDays(-2), -2 }, { DateTime.Now.AddDays(-1), -1 }, { DateTime.Now.AddDays(3), 3 }, }; var specifiedDate = DateTime.Now; var distances = data .Select(p => new { Distance = Math.Abs((specifiedDate - p.Key).Ticks), p.Value }); var distance = long.MaxValue; int closestParameter; foreach (var pair in distances) { if (pair.Distance < distance) { distance = pair.Distance; closestParameter = pair.Value; } } |
Well, as an option, my favorite MinBy feature from the MoreLinq package:
using MoreLinq; // ... var dict = new Dictionary<DateTime, string>() { [new DateTime(2016, 1, 1)] = "прошедший Новый Год", [new DateTime(2016, 12, 31)] = "будущий Новый Год", [new DateTime(2014, 1, 5)] = "давным-давно" }; var today = DateTime.Now; var closestValue = dict.MinBy(kvp => (kvp.Key - today).Duration()).Value; // -> будущий Новый Год |
Use Linq, Luke ... :)
var RawData = new List<DateTime> () { { DateTime.Now.AddDays(-2) }, { DateTime.Now.AddDays(-1) }, { DateTime.Now.AddDays(3) } } var specifiedDate = DateTime.Now; var minDistance = RawData.Min(n => (n - specifiedDate).Duration()); var minDate = RawData.Where(n => (n - specifiedDate).Duration() == minDistance).ToList(); - oneThis is not quite true. This will give the minimum distance , but the date with the minimum distance is needed. - VladD
- Ok, wrap in another filter. - Mirdin
|
O(N*log(N)) + O(log(n)) + O(1) = O(N*log(N))), but the logic, IMHO, will be simpler. - Yaant