SortedList上有下限函数<k,v =“”>?</k>

时间:2009-02-27 12:15:13

标签: c# .net sortedlist

SortedList<K ,V>上有下限功能吗?该函数应返回等于或大于指定键的第一个元素。还有其他类支持这个吗?

伙计们 - 请再次阅读这个问题。 我不需要一个返回密钥的函数(如果它存在)。当没有确切的密钥匹配时,我对场景感兴趣。

我对O(log n)时间感兴趣。这意味着我对foreach循环没有问题,而是希望有一种有效的方法。

我已经对此做了一些测试。

Linq语句既没有被编译器也没有运行时机器优化,因此它们遍历所有集合元素并且速度慢O(n)。根据Mehrdad Afshari的回答,这是一个二进制搜索,在Keys集合的O(log n)中工作:

public static int FindFirstIndexGreaterThanOrEqualTo<T>(
            this IList<T> sortedCollection, T key
        ) where T : IComparable<T> {
    int begin = 0;
    int end = sortedCollection.Count;
    while (end > begin) {
        int index = (begin + end) / 2;
        T el = sortedCollection[index];
        if (el.CompareTo(key) >= 0)
            end = index;
        else
            begin = index + 1;
    }
    return end;
}

6 个答案:

答案 0 :(得分:20)

二进制搜索SortedList.Keys集合。

我们走了。这是O(log n ):

private static int BinarySearch<T>(IList<T> list, T value)
{
    if (list == null)
        throw new ArgumentNullException("list");
    var comp = Comparer<T>.Default;
    int lo = 0, hi = list.Count - 1;
    while (lo < hi) {
            int m = (hi + lo) / 2;  // this might overflow; be careful.
            if (comp.Compare(list[m], value) < 0) lo = m + 1;
            else hi = m - 1;
    }
    if (comp.Compare(list[lo], value) < 0) lo++;
    return lo;
}

public static int FindFirstIndexGreaterThanOrEqualTo<T,U>
                          (this SortedList<T,U> sortedList, T key)
{
    return BinarySearch(sortedList.Keys, key);
}

答案 1 :(得分:4)

我会选择LINQ(假设您使用的是C#3),但是使用带有谓词的FirstOrDefault的重载:

first = sortedList.FirstOrDefault(x => x >= theObjectForComparison);

(许多其他Enumerable方法也可以使用谓词,这是一个很好的快捷方式)

答案 2 :(得分:3)

不知道一个,但这是一个简单的LINQ语句:

first = sortedList.Where(x => x >= theObjectForComparison).FirstOrDefault();

first将是通过比较的第一个对象或default(T)(通常为null)。

修改

DaveW的版本:

first = sortedList.FirstOrDefault(x => x >= theObjectForComparison);

做同样的工作,但可能更快,你必须测试它。

答案 3 :(得分:0)

或者您可以编写自己的扩展方法来执行此操作。请注意,所有这些功能都不能保证有效。

答案 4 :(得分:0)

<块引用>

SortedList 上有下界函数吗?功能 应该返回等于或大于指定的第一个元素 键。

这个例子是作为 SortedList 的扩展实现的,它返回大于或等于提供的键的最小元素的值。如果所有键都小于提供的键或提供了空列表,则返回默认值(TValue)

public static TValue LowerBound<TKey, TValue>(this SortedList<TKey, TValue> list, TKey key) {
  if (list.Count == 0)
    return default;

  var comparer = list.Comparer;
  if (comparer.Compare(list.Keys[list.Keys.Count - 1], key) < 0)
    return default; // if all elements are smaller, then no lower bound

  int first = 0, last = list.Count - 1;
  while (first < last) {
    var middle = first + (last - first) / 2;
    if (comparer.Compare(list.Keys[middle], key) >= 0)
      last = middle;
    else
      first = middle + 1;
  }
  return list[list.Keys[last]];
}

用法示例:

SortedList<string, Object> myList = new SortedList<string, Object>();
...
var value = myList.LowerBound<string, Object>("theKey");

答案 5 :(得分:-2)

希望这应该更快,具体取决于SortedList的实现。

public static int FindFirstIndexGreaterThanOrEqualTo<K, V>(
        this SortedList<K, V> sortedCollection, K key
    ) where V : new()
{
    if (sortedCollection.ContainsKey(key))
    {
        return sortedCollection.IndexOfKey(key);
    }
    sortedCollection[key] = new V();
    int retval = sortedCollection.IndexOfKey(key);
    sortedCollection.Remove(key);
    return retval;
}