【问题标题】:Doing a range lookup in C# - how to implement在 C# 中进行范围查找 - 如何实现
【发布时间】:2012-01-21 18:42:20
【问题描述】:

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

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

第一组在哪里分别返回1、2、3的值?

我不太了解这段代码是如何完成的。发送。

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

【问题讨论】:

    标签: c# range


    【解决方案1】:

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

    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 返回的索引是从零开始的

    【讨论】:

    • 什么是IRangeComparer?我使用Array.BinarySearch 所以它需要IComparerIComparer 只接受比较&lt;T&gt;,而不是&lt;A&lt;T&gt;, T&gt;。如果是&lt;A&lt;T&gt;, T&gt;,那么当它比较T vs A&lt;T&gt; 而不是A&lt;T&gt; vs T 时会发生什么?
    • @123iamking: IRangeComparer 在 OP 的问题中定义。我的答案是专门为它写的,不是为Array.BinarySearch
    猜你喜欢
    • 1970-01-01
    • 2012-02-29
    • 2017-07-09
    • 2011-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-09
    • 2010-12-09
    相关资源
    最近更新 更多