2009-02-27 13 views
19

¿Hay una función de límite inferior en SortedList<K ,V>? La función debe devolver el primer elemento igual o superior a la clave especificada. ¿Hay alguna otra clase que apoye esto?¿Hay una función de límite inferior en una SortedList <K ,V>?

Chicos - por favor lea la pregunta una vez más. No necesito una función que devuelva la clave si está presente. Me interesa el escenario cuando no coinciden las claves exactas.

Me gusta 0 (horario de verano). Significa que no tengo un problema con foreach loop, pero me gustaría tener una forma eficiente de hacerlo.

He hecho algunas pruebas al respecto.

Las sentencias de Linq no son optimizadas ni por el compilador ni por la máquina de tiempo de ejecución, por lo que recorren todos los elementos de la colección y son lentos O (n). Sobre la base de la respuesta Mehrdad Afshari, aquí es una búsqueda binaria que funciona en O (log n) en la Recogida de llaves:

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

Respuesta

18

binario Buscar en toda la SortedList.Keys.

Aquí vamos. Esto es 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); 
} 
+0

¿No se genera la colección cada vez que leemos la propiedad Keys? – agsamek

+1

agsamek: No, no está regenerado. Devolverá una instancia de la clase interna KeyList que proporciona acceso directo a los elementos en la colección original. Nada se copia en el proceso. –

+0

La "no copia de Claves y valores" es la principal diferencia con SortedDictionary –

3

no tiene conocimiento de uno, pero es una declaración LINQ simple:

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

first bien será el primer objeto que pasa la comparación o default(T) (que normalmente es null).

Editar

versión de DaveW:

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

hace el mismo trabajo, pero potencialmente podría ser más rápido, que tendría que probarlo sin embargo.

+4

Lo intenté, no parece ser O (log n) –

4

me gustaría ir con LINQ (suponiendo que estés usando C# 3), pero utilizando la sobrecarga de FirstOrDefault que tiene un predicado:

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

(muchos de los otros métodos enumerables también puede tomar predicados que es un buen atajo)

-1

O puede escribir su propio método de extensión para hacer esto. Tenga en cuenta que no se garantiza que todas esas funciones entren en un enclaustramiento.

-1

Esperemos que esto debería ser más rápido, dependiendo de la implementación de 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; 
} 
+1

Este es el O (n) peor caso. No muy bueno. – nawfal

Cuestiones relacionadas