2014-07-19 64 views
1

二進制搜索返回錯誤的值,即使列表已排序。這裏是清單:列表<T>二進制搜索返回錯誤值

1707 ABCD 
1707 XXXX 
1725 DEFG 
1725 HIJK 
1725 LMNOP 

我從預先排序按時間(第一列)的文件這個名單,所以我沒有在我的代碼進行排序這一點。當我在1725 DEFG上進行二分搜索時,它會在按位補碼前返回給我1725 LMNOP。如果我做了一個按位補碼,結果將是1725 HIJK。

這是爲什麼?

這裏的實現:

public class RecComparer: IComparer<MyData> 
{ 
public int Compare(MyData x, MyData y) 
{ 
    if (x.DateDetails == null) 
    { 
     if (y.DateDetails == null) 
     { 
          return 0; 
     } 
     else 
     { 

      return -1; 
     } 
    } 
    else 
    { 

     if (y.DateDetails == null) 
         { 
      return 1; 
     } 
     else 
     { 
      int retval = x.DateDetails.Length.CompareTo(y.DateDetails.Length); 

      if (retval != 0) 
      { 

       return retval; 
      } 
      else 
      { 

       return x.DateDetails.CompareTo(y.DateDetails); 
      } 
     } 
    } 
} 
} 

這裏的調用二分查找:

lookAhead = recordList.BinarySearch(lookAheadtime, (IComparer<MyData>)rc); 

任何理由就是爲什麼它的行爲的方式。

編輯:

public class MyData 
{ 
    public string DateDetails { get; set; } 
    public string TrackDetails { get; set; } 
} 
+0

我不認爲二進制搜索與非唯一密鑰一起工作 –

+0

那麼實現這一點的最佳方式是什麼。 – user726720

+0

@DarrenKopp:如果是這種情況,我還應該包括列表的第二列,而不是僅僅搜索第一列。 – user726720

回答

0

更新#2:在副本列表使用自定義比較二進制搜索。

假設,在「1707 ABCD」,「1707」是DateDetails和「ABCD」是TrackDetails,你有數據的兩個字段的陣列,其已排序中的兩個字段的一個順序,即DateDetails。因此可能有多個條目具有相同的DateDetails

如果您執行BinarySearch,它將返回指定的DateDetails,中的一個條目,而不一定是第一個。然後你必須向後掃描找到第一個。

public static class ListHelper 
{ 
    /// <summary> 
    /// Return the zero-based index of the first matching item in the sorted List, 
    /// if a match for item is found; otherwise, a negative number that is the bitwise 
    /// complement of the index of the next element that is larger than item or, if there is 
    /// no larger element, the bitwise complement of Count. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="list"></param> 
    /// <param name="item"></param> 
    /// <param name="comparer"></param> 
    /// <returns>The zero-based index of the first matching item in the sorted List, 
    /// if item is found; otherwise, a negative number that is the bitwise complement 
    /// of the index of the next element that is larger than item or, if there is 
    /// no larger element, the bitwise complement of Count.</returns> 
    public static int BinarySearchFirst<T>(this List<T> list, T item, IComparer<T> comparer) 
    { 
     int start = list.BinarySearch(item, comparer); 
     for (; start > 0 && comparer.Compare(list[start], list[start - 1]) == 0; start--) 
      ; 
     return start; 
    } 
    /// <summary> 
    /// Find the zero-based indices of the first and last matching items in the sorted List, 
    /// if a match for item is found; otherwise, a negative number for both that is the bitwise 
    /// complement of the index of the next element that is larger than item or, if there is 
    /// no larger element, the bitwise complement of Count. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="list"></param> 
    /// <param name="item"></param> 
    /// <param name="comparer"></param> 
    /// <param name="start">The zero-based index of the first matching item in the List, 
    /// if item is found; otherwise, a negative number that is the bitwise complement 
    /// of the index of the next element that is larger than item or, if there is 
    /// no larger element, the bitwise complement of Count.</param> 
    /// <param name="end">The zero-based index of the first matching item in the sorted List, 
    /// if item is found; otherwise, a negative number that is the bitwise complement 
    /// of the index of the next element that is larger than item or, if there is 
    /// no larger element, the bitwise complement of Count.</param> 
    /// <returns>true if found, else false</returns> 
    public static bool BinarySearchRange<T>(this List<T> list, T item, IComparer<T> comparer, out int start, out int end) 
    { 
     start = end = list.BinarySearch(item, comparer); 
     if (start < 0) 
      return false; 
     for (; start > 0 && comparer.Compare(list[start], list[start - 1]) == 0; start--) 
      ; 
     for (int last = list.Count - 1; end < last && comparer.Compare(list[end], list[end + 1]) == 0; end++) 
      ; 
     return true; 
    } 
} 
+0

這適用於我。我必須做一個改變才能使它工作:for(; start> 0 && rc.Compare(recordList [〜lookAhead],recordList [start - 1])== 0; start--) ; – user726720

0

我不知道如果我理解這個問題,但是你就不能使用LINQ查詢列表?

recordList.Where(x=>x.columnName == 1725).First(); 
+0

不,情況並非如此,這只是一個例子,上面我遇到了麻煩。如果我在LINQ中使用您的代碼,我無法搜索最接近的值 – user726720