2010-02-20 34 views
5

如果我有日期和值的集合。我想這是任何值:在最近日期收集中查找項目

  1. 關聯到集合中的日期
  2. 如果不存在的話,我想兩點都是圍繞我找點之間的線性插值

ao,這裏是一個簡單的例子。如果集合是:

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

如果我找2010/6/1我會得到一個值回250,我可以使用任何集合如果一個比另一個(字典,陣列等解決好..)

回答

2

一個簡單的排序(在日期)列表就足夠了。只需找到最近的日期(我們稱之爲d1),該日期小於或等於您正在查找的日期(我們稱之爲d)。假設沒有重複的日期,下一個日期d2將通過d

現在,如果值V1對應D1V2對應D2那麼你正在尋找的價值V1 +(V2 - V1)/(D2 - d1)*(d-d1)。

+0

我想看看除了線性搜索之外是否有更快的方法來做 – leora 2010-02-21 22:59:55

+0

還有,這裏有人提到過:如果你的列表已經排序,你可以進行二分搜索。 – 2010-02-22 07:22:54

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) 
     ... 
    } 
} 
+0

@Vlad - 什麼是容器和針頭? – leora 2010-02-20 18:28:48

+0

'needle'是一個'DateTime'你正在尋找的是 – Vlad 2010-02-20 18:32:20

+0

'container'是錯誤的,它確實需要''haystack' – Vlad 2010-02-20 18:34:50

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; 

當然的代碼可能不是最好的,但你的想法:用列表,排序,然後做二分查找。

查找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

+0

這是對BinarySearch的深入瞭解。謝謝。 – Echilon 2011-10-09 14:44:18

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); 
    } 
} 
+0

剛剛編輯。算法測試。 – 2013-02-02 20:20:01

+0

作品,但表現是O(N) – 2013-04-02 15:56:24

+0

@TheodoreZographos是一個規格/要求?如果它有效;有用 – 2013-04-24 10:15:38