2012-01-23 55 views
1

鑑於「原代碼」如下圖所示(從螺紋Doing a range Lookup做在C#中的範圍查找 - 如何實現部分DEUX

我想實現一個TableLookUp方法,將包裹二分查找程序。我改變了Range類來接受一個value屬性。我創建了TableLookUp例程,但我知道這是錯誤的。我不知道如何調用BinarySearch方法來實現這個功能。泛型讓我感到困惑。

Tx提前!

值稱爲可能是這樣的:

var ranges = new Range<int>[] 
      { 
       new Range<int>(1, 10000, 22), 
       new Range<int>(10001, 40000, 33), 
       new Range<int>(40001, int.MaxValue, 44) 
      }; 

更換範圍類下面的代碼:

public class Range<TValue> 
     where TValue : IComparable<TValue> 
    { 
     public TValue Min { get; set; } 
     public TValue Max { get; set; } 
     public int Value { get; set; } 

     public Range(TValue min, TValue max, int value) 
     { 
      this.Min = min; 
      this.Max = max; 
      this.Value = value; 
     } 
    } 

添加包裝,以二進制搜索:

public static int LookUpTable<TRange, TValue>(IList<TRange> ranges, TValue value, IRangeComparer<TRange, TValue> comparer) 
    { 
     int indexToTable = BinarySearch(ranges, value, comparer); 
     Range<TRange> lookUp = ranges[indexToTable]; 
     return lookUp.Value; 
    } 

在更換調用代碼主要是這樣的:

Console.WriteLine(LookUpTable(ranges, 7, rangeComparer)); 
Console.WriteLine(LookUpTable(ranges, 10007, rangeComparer)); 
Console.WriteLine(LookUpTable(ranges, 40007, rangeComparer)); 
Console.WriteLine(LookUpTable(ranges, 1, rangeComparer)); 

原代碼:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace TestConsole 
{ 
    class Program 
    { 

     public interface IRangeComparer<TRange, TValue> 
     { 
      /// <summary> 
      /// Returns 0 if value is in the specified range; 
      /// less than 0 if value is above the range; 
      /// greater than 0 if value is below the range. 
      /// </summary> 
      int Compare(TRange range, TValue value); 
     } 


     /// <summary> 
     /// See contract for Array.BinarySearch 
     /// </summary> 
     public static int BinarySearch<TRange, TValue>(IList<TRange> ranges, 
                 TValue value, 
                 IRangeComparer<TRange, TValue> comparer) 
     { 
      int min = 0; 
      int max = ranges.Count - 1; 

      while (min <= max) 
      { 
       int mid = (min + max)/2; 
       int comparison = comparer.Compare(ranges[mid], value); 
       if (comparison == 0) 
       { 
        return mid; 
       } 
       if (comparison < 0) 
       { 
        min = mid + 1; 
       } 
       else if (comparison > 0) 
       { 
        max = mid - 1; 
       } 
      } 
      return ~min; 
     } 

     public class Range<TValue> 
      where TValue : IComparable<TValue> 
     { 
      public TValue Min { get; set; } 
      public TValue Max { get; set; } 

      public Range(TValue min, TValue max) 
      { 
       this.Min = min; 
       this.Max = max; 
      } 
     } 

     public class RangeComparer<TValue> : IRangeComparer<Range<TValue>, TValue> 
      where TValue : IComparable<TValue> 
     { 
      /// <summary> 
      /// Returns 0 if value is in the specified range; 
      /// less than 0 if value is above the range; 
      /// greater than 0 if value is below the range. 
      /// </summary> 
      public int Compare(Range<TValue> range, TValue value) 
      { 
       // Check if value is below range (less than min). 
       if (range.Min.CompareTo(value) > 0) 
        return 1; 

       // Check if value is above range (greater than max) 
       if (range.Max.CompareTo(value) < 0) 
        return -1; 

       // Value is within range. 
       return 0; 
      } 
     } 


     static void Main(string[] args) 
     { 

      var ranges = new Range<int>[] 
      { 
       new Range<int>(1, 10000), 
       new Range<int>(10001, 40000), 
       new Range<int>(40001, int.MaxValue), 
      }; 

      var rangeComparer = new RangeComparer<int>(); 

      Console.WriteLine(BinarySearch(ranges, 7, rangeComparer));  // gives 0 
      Console.WriteLine(BinarySearch(ranges, 10007, rangeComparer)); // gives 1 
      Console.WriteLine(BinarySearch(ranges, 40007, rangeComparer)); // gives 2 
      Console.WriteLine(BinarySearch(ranges, 1, rangeComparer));  // gives 0 
      Console.WriteLine(BinarySearch(ranges, 10000, rangeComparer)); // gives 0 
      Console.WriteLine(BinarySearch(ranges, 40000, rangeComparer)); // gives 1 
      Console.WriteLine(BinarySearch(ranges, 40001, rangeComparer)); // gives 2 

      Console.WriteLine("Press any key to continue..."); 
      Console.ReadKey(true); 
     } 
    } 
} 
+3

什麼是你的問題? – StriplingWarrior

+0

如何修復LookUpTable方法,使其工作? – user1161137

+0

它在做什麼而不是工作? – phoog

回答

1
public static int LookUpTable<TRange, TValue>(IList<TRange> ranges, TValue value, IRangeComparer<TRange, TValue> comparer) 
    where TRange : Range<TValue> // Specify what you know about TRange and TValue 
    where TValue : IComparable<TValue> 
{ 
    int indexToTable = BinarySearch(ranges, value, comparer); 
    TRange lookUp = ranges[indexToTable]; // lookUp is TRange, not Range<TRange> 
    return lookUp.Value; 
} 
+0

啊..好的,所有這些畫面都令人困惑。我曾嘗試過TRange,但隨後它給lookUp.Value一個錯誤,指出「'TRange'不包含'Value'的定義,並且沒有擴展menthod'Value'...」。我猜想添加「WHER TRange:Range 」是必要的嗎?!?我不明白爲什麼?它不應該仍然有效,可以隱式轉換嗎? – user1161137

+0

@ user1161137:隱式轉換爲什麼?有許多對象類型沒有'Value'屬性:編譯器爲什麼應該假定你正在談論'Range'對象?如果你通過'List '作爲第一個參數呢?如果沒有'where'過濾器,就沒有什麼可以阻止這種情況發生,但是在'int'上訪問'.Value'屬性是沒有意義的,對嗎? 「where」過濾器是該方法知道您期望'TRange'完全代表'Range'的唯一方法。 – StriplingWarrior

+0

StriplingWarrior:很好解釋。 user1161137:抱歉沒有跟進原始問題,但我估計是在與你不同的時區(UTC + 1),現在只能閱讀你的評論。 – Douglas