在C#中进行范围查找 - 如何实现

时间:2012-01-20 21:42:23

标签: c# range

我正在尝试理解如何实现Jon Skeet在线程中找到的代码: Doing a range lookup in C#?

有人可以使用以下内容提供设置示例: 1-10000,10001-40000,40000 +

其中第一组分别返回值1,2,3?

我不太清楚这段代码是如何完成的。 TX。

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

1 个答案:

答案 0 :(得分:2)

您需要很好地掌握泛型以理解此代码。这是一个功能实现:

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
}

不要忘记:

  • 范围必须按升序排列
  • 范围不得重叠
  • BinarySearch返回的索引从零开始