C# 从字典中获取最接近的可用值
我有一本字典C# 从字典中获取最接近的可用值,c#,dictionary,C#,Dictionary,我有一本字典 说 此处没有“2018-04-01”键, 因此,我需要最接近可用值的任何。 它可以是“2018-03-01”或“2018-05-01”的值 现在我希望它被清除。 请不要冒犯,英语不是我的母语。您需要一本有序的词典,不仅如此,您还需要一个自定义比较器来查找最接近键的日期。 请参阅下面的示例代码 void Main() { OrderedDictionaryByDateTime<double> data = new OrderedDictionaryByDateTi
说 此处没有“2018-04-01”键,
因此,我需要最接近可用值的任何。
它可以是“2018-03-01”或“2018-05-01”的值
现在我希望它被清除。
请不要冒犯,英语不是我的母语。您需要一本有序的词典,不仅如此,您还需要一个自定义比较器来查找最接近键的日期。 请参阅下面的示例代码
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);
}
}
void Main()
{
OrderedDictionaryByDateTime数据=新的OrderedDictionaryByDateTime();
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明天=DateTime.Now.AddDays(1);
var oneHourBefore=DateTime.Now.AddHours(-1);
var TheDayafter明天=DateTime.Now.AddDays(2);
var昨天=DateTime.Now.AddDays(-1);
var fourDaysInThePast=DateTime.Now.AddDays(-4);
data.getvalueclosesttotheatetimekey(明天);//应为1.1
data.GetValueClosestToTheDateTimeKey(一小时前);//应为1.1
data.getValueClosestheDateTimeKey(昨天);//应为1.2
data.getValuesClosestheDateTimeKey(后天);//应为1.3
data.GetValueClosestToTheDateTimeKey(FourDaySintheast);//应为1.5
}
公共类OrderedDictionaryByDateTime:列表
{
专用只读词典_Dictionary=新词典();
public void Add(日期时间键,TValue值)
{
添加(新的KeyValuePair(键,值));
_添加(键,计数-1);
}
公共TValue获取(日期时间键)
{
var idx=_字典[键];
返回此[idx].值;
}
公共TValue GetValuesClosestheDateTime键(DateTime键)
{
var closestDate=_dictionary.Keys.OrderBy(t=>Math.Abs((t-key.Ticks)).First();
返回Get(关闭日期);
}
}
如果你需要最接近的值,你需要循环通过字典,取最小的时间跨度,记住最小的时间跨度并返回该日期时间
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;
TimeSpan TimeSpan=DateTime.MinValue-DateTime.MaxValue;
双重返回日期;
foreach(MyData.Keys中的var键)
{
如果(键您可以使用下面的代码
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;
}
}
按键(DateTime)对字典进行编码排序,并查找更大或相等的日期值。如果有有效记录,则返回第一个值,否则返回-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(字典源,日期时间日期)
{
if(source.Where(x=>x.Key>=date).OrderBy(x=>x.Key).Count()>0)
返回source.Where(x=>x.Key>=date).OrderBy(x=>x.Key).FirstOrDefault()值;
其他的
返回-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;
}
}
public double?getData(字典源,日期时间日期)
{
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 x.Key).Count()>0?source.Where(x=>x.Key x.Key).FirstOrDefault().Key:DateTime.MinValue;
长时间_差=-1;
长向下_差=-1;
if(up!=DateTime.MinValue)
up_difference=up.Ticks-date.Ticks;
如果(向下!=DateTime.MinValue)
down_difference=date.Ticks-down.Ticks;
//没有更高或更高的值
如果(上下之差==-1和下之差==-1)
返回null;
否则如果(上下差异!=-1和下下差异!=-1)
{
if(上下差值)
返回source.Where(x=>x.Key==up).FirstOrDefault().Value;
其他的
返回source.Where(x=>x.Key==down).FirstOrDefault()值;
}
否则,如果(向上差值!=-1)
{
返回source.Where(x=>x.Key==up).FirstOrDefault().Value;
}
其他的
{
返回source.Where(x=>x.Key==down).FirstOrDefault()值;
}
}
您只需将字典放入已排序的字典中,然后进行二进制搜索即可。
如果密钥不存在,则左侧的项是最近的项。
这不适用于~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]];
}
publicstaticdouble-GetMyData(Dictionary-MyData,DateTime-Date)
{
var sorted=新的SortedDictionary(MyData);
var keys=新列表(排序的.keys);
var index=keys.BinarySearch(日期);
如果(索引>=0)返回已排序的[键[索引];
其他的
返回已排序的[键[~索引-1]];
}
我想我已经找到了解决办法
步骤1:对小于给定日期的键进行排序(降序),并获取FirstOrDefault=>PreviousKey
步骤2:对大于给定日期的键进行排序(降序),并取FirstOrDefault=>NextKey
步骤3:现在检查它们之间的差异
步骤4:如果(Date
-PreviousKey
)>(NextKey
-Date
),则取NextKey
否则PreviousKey
=>FoundKey
步骤5:现在,返回MyData[FoundKey]字典不是您需要的数据结构。您需要一个有序的数据结构。类似于列表。或者您可以使用字典+排序列表的组合。如果我将其作为列表,那么如何获得该值。问题是找到最近的可用日期(键)然后是该键的值。无论如何,该键是已经排序的日期。我只需要获取最近的可用键的值。你能解释你的实际任务/问题吗?以哪种方式也是最近的?我可能会使用八叉树。无论如何,你的问题可能太复杂了
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;
}
}
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]];
}