I have a data structure that uses a Dictionary<ID,TimeSeries>
to hold time series for different products. TimeSeries
is implemented as something holding an array of Point
, which contain a DateTime
and a double
.
Its interface is:
TimeSeries{
int Length{ get; }
Point ElementAt(int index);
DateTime StartTime { get; }
DateTime EndTime { get; }
}
Given a pair of elements of such data structure I need to find the first time instant where they diverge. For my definition of divergence, if a dictionary contains an element and the other doesn't I need to return the time of the first point of the TimeSeries
I have.
This is the code I'm using to compute the difference and that I'd like you to review and comment:
bool TryFindFirstDivergenceTime(Dictionary<ID, TimeSeries> baseline, Dictionary<ID, TimeSeries> other, out DateTime firstDivergenceTime)
{
firstDivergenceTime = default(DateTime);
foreach(var baselineIDSeriesPair in baseline)
{
if(other.ContainsKey(baselineIDSeriesPair.Key))
{
firstDivergenceTime = Min(FindFirstDivergenceTime(baselineIDSeriesPair.Value, other[baselineIDSeriesPair.Key]), firstDivergenceTime);
}
else
{
firstDivergenceTime = Min(baselineIDSeriesPair.Value.Start, firstDivergenceTime);
}
}
foreach(var otherIDSeriesPair in other)
{
if(!baseline.ContainsKey(otherIDSeriesPair.Key))
{
firstDivergenceTime = Min(otherIDSeriesPair.Value.Start, firstDivergenceTime);
}
}
return firstDivergenceTime != default(DateTime);
}
public DateTime Min(DateTime first, DateTime second)
{
if(first == default(DateTime))
return second;
if(second == default(DateTime))
return first;
return new DateTime(Math.Min(first.Ticks, second.Ticks));
}
DateTime FindFirstDivergenceTime(TimeSeries first, TimeSeries second)
{
if(first.Length != second.Length)
{
throw new ArgumentException();
}
for(var i=0; i < first.Length; i++)
{
if(! first.ElementAt(i).Equals(second.ElementAt(i)))
{
return Min(first.ElementAt(i).Time, second.ElementAt(i).Time);
}
}
return default(DateTime);
}
I have the feeling that I am not approaching the problem in the right way as the code contains the repetition of the logic to find the time of the first difference when I don't have the same product in both the dictionaries.
The other think that I don't particularly like is that I find myself breaking th symmetry and using for on dictionary Key
and Value
from its IEnumerable
, while from the other I need to perform a lookup.
How would you address those issues?
Min
andFindFirstDivergenceTime
, so IMO they are quite relevant. Also, this doesn't look like it would compile (see duplicateStartTime
definitions inTimeSeries
and first use ofotherIDSeriesPair
in theTryFindFirstDivergenceTime
method. \$\endgroup\$Min
andFindFirstDivergenceTime
method implementations \$\endgroup\$first.Zip(second, (a, b) => { . . . })
of some kind instead of the foreaches. That does require the order to be the same, though. \$\endgroup\$