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]];
    }