我正在字典
说
Dictionary<DateTime, double> MyData
现在我想从字典中获取值。
但是,如果密钥不存在,那么我需要取最接近的值。
让我们调用函数
double GetMyData(Dictionary<DateTime, double> MyData, DateTime Date)
{
if(MyData.ContainsKey(Date)
{
return MyData[Date];
}
else
{
//return the nearest available value.
// if Date is '2018-01-01', then try to look for next date,
// It can be '2018-01-02' or even '2017-12-31'
// Here aim is to get the nearest available value.
}
}
编辑:
样本数据:
MyData['2018-01-01'] = 420.0;
MyData['2018-02-01'] = 220.0;
MyData['2018-03-01'] = 320.0;
MyData['2018-05-01'] = 210.0;
MyData['2018-06-01'] = 220.0;
MyData['2018-07-01'] = 230.0;
MyData['2018-08-01'] = 240.0;
此处密钥'2018-04-01'不可用,
因此,我需要任何最接近的可用值。
它可以是'2018-03-01'或'2018-05-01'的值
现在希望它已清除。
而且请不要冒犯,英语不是我的母语。
答案 0 :(得分:2)
您将需要一个有序词典,不仅如此,还需要一个自定义比较器来找到最接近该键的日期
请参阅下面的最小示例代码
void Main()
{
OrderedDictionaryByDateTime<double> data = new OrderedDictionaryByDateTime<double>();
data.Add(DateTime.Now, 1.1);
data.Add(DateTime.Now.AddDays(-1), 1.2);
data.Add(DateTime.Now.AddDays(2), 1.3);
data.Add(DateTime.Now.AddDays(3), 1.4);
data.Add(DateTime.Now.AddDays(-5), 1.5);
var tomorrow = DateTime.Now.AddDays(1);
var oneHourBefore = DateTime.Now.AddHours(-1);
var theDayAfterTomorrow = DateTime.Now.AddDays(2);
var yesterday = DateTime.Now.AddDays(-1);
var fourDaysInThePast = DateTime.Now.AddDays(-4);
data.GetValueClosestToTheDateTimeKey(tomorrow); // should be 1.1
data.GetValueClosestToTheDateTimeKey(oneHourBefore); // should be 1.1
data.GetValueClosestToTheDateTimeKey(yesterday); // should be 1.2
data.GetValueClosestToTheDateTimeKey(theDayAfterTomorrow); // should be 1.3
data.GetValueClosestToTheDateTimeKey(fourDaysInThePast); // should be 1.5
}
public class OrderedDictionaryByDateTime<TValue> : List<KeyValuePair<DateTime, TValue>>
{
private readonly Dictionary<DateTime, int> _dictionary = new Dictionary<DateTime, int>();
public void Add(DateTime key, TValue value)
{
Add(new KeyValuePair<DateTime, TValue>(key, value));
_dictionary.Add(key, Count - 1);
}
public TValue Get(DateTime key)
{
var idx = _dictionary[key];
return this[idx].Value;
}
public TValue GetValueClosestToTheDateTimeKey(DateTime key)
{
var closestDate = _dictionary.Keys.OrderBy(t => Math.Abs((t - key).Ticks)).First();
return Get(closestDate);
}
}
答案 1 :(得分:1)
您只需将字典放入经过排序的字典中,然后进行二进制搜索。 如果该键不存在,则左侧的项目是最接近的项目。 这不适用于〜index-1变为-1等的边界情况...
public static double GetMyData(Dictionary<DateTime, double> MyData, DateTime Date)
{
var sorted = new SortedDictionary<DateTime, double>(MyData);
var keys = new List<DateTime>(sorted.Keys);
var index = keys.BinarySearch(Date);
if (index >= 0) return sorted[keys[index]];
else
return sorted[keys[~index - 1]];
}
答案 2 :(得分:0)
如果您需要最接近的值,则需要遍历字典并以最小的时间跨度记住最小的时间并返回该DateTime。
TimeSpan timeSpan=DateTime.MinValue-DateTime.MaxValue;
double returnDate;
foreach(var key in MyData.Keys)
{
if(key<Date)
{
var dif = Date-key;
if(dif<timeSpan)
{
timeSpan=dif;
returnDate=MyData[key];
}
}
else
{
var dif = key-Date;
if(dif<timeSpan)
{
timeSpan=dif;
returnDate=MyData[key];
}
}
}
return returnDate;
答案 3 :(得分:0)
您可以在下面使用代码,
按键(DateTime)对字典排序,并查找GreaterOrEqual日期值。如果存在有效记录,则返回第一个值,否则返回-1
public double? getData(Dictionary<DateTime,double> source, DateTime date)
{
if (source.Where(x => x.Key >= date).OrderBy(x => x.Key).Count() > 0)
return source.Where(x => x.Key >= date).OrderBy(x => x.Key).FirstOrDefault().Value;
else
return -1;
}
如果要获取最接近的值(向上或向下),可以使用下面的代码,
public double? getData(Dictionary<DateTime,double> source, DateTime date)
{
DateTime up = source.Where(x => x.Key >= date).OrderBy(x => x.Key).Count() > 0 ? source.Where(x => x.Key >= date).OrderBy(x => x.Key).FirstOrDefault().Key : DateTime.MinValue;
DateTime down = source.Where(x => x.Key <= date).OrderByDescending(x => x.Key).Count() > 0 ? source.Where(x => x.Key <= date).OrderByDescending(x => x.Key).FirstOrDefault().Key : DateTime.MinValue;
long up_difference = -1;
long down_difference = -1;
if (up != DateTime.MinValue)
up_difference = up.Ticks - date.Ticks;
if (down != DateTime.MinValue)
down_difference = date.Ticks - down.Ticks;
// There are no values upper or higher
if (up_difference == -1 && down_difference == -1)
return null;
else if (up_difference != -1 && down_difference != -1)
{
if(up_difference < down_difference)
return source.Where(x => x.Key == up).FirstOrDefault().Value;
else
return source.Where(x => x.Key == down).FirstOrDefault().Value;
}
else if(up_difference != -1)
{
return source.Where(x => x.Key == up).FirstOrDefault().Value;
}
else
{
return source.Where(x => x.Key == down).FirstOrDefault().Value;
}
}
答案 4 :(得分:0)
我想我已经找到了解决方案。
Step1:对小于给定日期的键进行排序(降序),并采用FirstOrDefault => PreviousKey
步骤2:对大于给定日期的键进行排序(降序),并采用FirstOrDefault => NextKey
Step3:现在检查它们之间的区别
步骤4:如果(Date
-PreviousKey
)>(NextKey
-Date
),则取NextKey
否则PreviousKey
=> FoundKey
步骤5:现在,返回MyData [FoundKey]