在C#中进行范围查找?

时间:2009-01-17 22:58:15

标签: c#

我有一个非重叠范​​围的列表(数字范围,例如500-1000,1001-1200 ......等),是否有一种优雅而快速的方法只通过一个数字进行查找?我可以使用List.BinarySearch()或Array.BinarySearch()但我必须传递范围对象的类型(Array.BinarySearch(T [],T)),我可以传递一个虚拟范围对象并完成工作(只与范围开始进行比较)但我想知道是否可以通过传递整数并获取范围对象以更清洁的方式完成,是否有办法实现这一目标?

3 个答案:

答案 0 :(得分:12)

三个选项:

  • 创建一个虚拟范围并将其吸收。 Urgh。
  • 仅针对此案例手工制作二进制搜索。还不错。
  • 给定IRangeComparer,对任何IList和TValue进行二进制搜索。我在这里的名字“TRange”并不狂热 - 我们不一定会谈论范围,而只是根据两种不同类型之间的比较找到合适的位置。

第三个选项会某些,如:

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 :(得分:1)

如果您有.Net 3.5或更高版本,请尝试

foundRange = yourList.Where(range =› range.BottomNumber ‹= searchInt && range.TopNumber ›= searchInt).FirstOrDefault();

答案 2 :(得分:0)

如果你有很多范围并且真的关心性能,你可以创建一个AVL type of tree组成的范围(最小,最大)对,但是在范围的最低部分排序。

但是,如果你没有很多范围可以将事情分类,那么这项工作几乎没有任何好处。