在最近日期的集合中查找项目

时间:2010-02-20 17:57:11

标签: c# datetime collections

如果我有一组日期和价值观。我希望获得以下值:

  1. 与集合中的日期相关联
  2. 如果它不存在,我想要在我正在寻找的点周围的两个点之间进行线性插值
  3. ao,这是一个简单的例子。如果集合是:

    Date   Value  
    1/1/2009   100  
    1/1/2010   200  
    1/1/2011   300  
    

    如果我正在寻找6/1/2010,我会得到一个250的值。我可以使用任何集合,如果一个比另一个更好(字典,数组等)。

4 个答案:

答案 0 :(得分:7)

您可以使用List类型来保存对,对它们进行排序并使用List.BinarySearch。

例如,您可以使用以下内容:

struct Pair
{
    public Pair(DateTime t, int v)
    {
        date = t;
        value = v;
    }
    public DateTime date;
    public int value;
}

    ....

    List<Pair> pairs = new List<Pair>();


    pairs.Add(new Pair(DateTime.Now, 100));
    pairs.Add(new Pair(DateTime.Now, 200));

    ....

    // Sort using the time.
    pairs.Sort(delegate(Pair pair1, Pair pair2) {
                           return  pair1.date.CompareTo( pair2.date);
                        }
              );

    // Do binary search.
    int index = pairs.BinarySearch(new Pair(dateToSearch, 0), 
                                   delegate(Pair pair1, Pair pair2) { 
                                       return pair1.date.CompareTo(pair2.date); 
                                   });

    if (index >= 0) {
        // Found the element!
        return pairs[index].value;
    }

    // If not found, List.BinarySearch returns the complement 
    // of the index where the element should have been.
    index = ~index;

    // This date search for is larger than any
    if (index == pairs.Count) {
        //
    }

    // The date searched is smaller than any in the list.
    if (index == 0) {
    }

    // Otherwise return average of elements at index and index-1.
    return (pairs[index-1].value + pairs[index].value)/2;

当然代码不是最好的,但你明白了:使用List,对它进行排序然后再做BinarySearch。

查找MSDN以获取更多信息。

列表:http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx

List.Sort:http://msdn.microsoft.com/en-us/library/3da4abas.aspx

List.BinarySearch:http://msdn.microsoft.com/en-us/library/3f90y839.aspx

答案 1 :(得分:2)

简单的排序(日期)列表就足够了。只需找到小于或等于您要查找的日期的最后日期(让我们称之为 d1 )(让我们称之为 d )。假设没有重复日期,下一个日期 d2 将超过 d

现在,如果值 v1 对应 d1 v2 对应 d2 ,那么您要查找的值是 v1 +( v2 - v1 )/( d2 - d1 )* ( d - d1 )。

答案 2 :(得分:2)

给定“日期列表”和“参考日期”,获取“最接近的n个数字”。 C#代码测试。

public class ClosestDate
{
    public void GetClosestDate(DateTime referenceDate, 
                                List<DateTime> listDates, int maxResults)
    {
        // final ordered date list
        List<DateTime> finalList = new List<DateTime>();

        DateTime selectedDate = DateTime.MaxValue;

        // loop number of results
        for (int i = 0; i < maxResults; i++)
        {
            // get next closest date
            int tempDistance = int.MaxValue;
            foreach (DateTime currentDate in listDates)
            {
                int currenDistance = this.DateDiff(currentDate, referenceDate);

                if (currenDistance < tempDistance)
                {
                    tempDistance = currenDistance;
                    selectedDate = currentDate;
                }
            }

            // build final list
            finalList.Add(selectedDate);
            // remove element from source list
            listDates.Remove(selectedDate);
        }

        // print results
        foreach (DateTime date in finalList)
        {
            Console.WriteLine(date.ToShortDateString());
        }

    }

    private int DateDiff(DateTime Date1, DateTime Date2)
    {
        TimeSpan time = Date1 - Date2;
        return Math.Abs(time.Days);
    }
}

答案 3 :(得分:0)

您可以尝试SortedDictionary。做那样的事情:

int FindInterpolated(DateTime needle)
{
    try
    {
        DateTime lower = haystack.First(key => haystack[key] <= needle);
        DateTime upper = haystack.Last(key => haystack[key] >= needle);
        int v1 = haystack[lower];
        int v2 = haystack[upper];
        long ticksLower = lower.Ticks;
        long ticksUpper = upper.Ticks;
        return (v1 * ticksLower + v2 * ticksUpper) / (ticksLower + ticksUpper);
    }
    catch (InvalidOperationException)
    {
        // thrown if needle is out of range
        // (not between smallest and biggest keys in the haystack)
        ...
    }
}