Diccionario revertido ordenado en .NET

¿Hay alguna forma de que pueda iterar hacia atrás (en reversa) a través de un SortedDictionary en c #?

¿O hay una forma de definir el SortedDictionary en orden descendente para empezar?

SortedDictionary no admite la iteración hacia atrás, pero tiene varias posibilidades para lograr el mismo efecto.

  1. Utilice .Reverse -Method (Linq). (Esto tendrá que calcular previamente toda la salida del diccionario, pero es la solución más simple)

     var Rand = new Random(); var Dict = new SortedDictionary(); for (int i = 1; i <= 10; ++i) { var newItem = Rand.Next(1, 100); Dict.Add(newItem, (newItem * newItem).ToString()); } foreach (var x in Dict.Reverse()) { Console.WriteLine("{0} -> {1}", x.Key, x.Value); } 
  2. Haga que el diccionario clasifique en orden descendente.

     class DescendingComparer : IComparer where T : IComparable { public int Compare(T x, T y) { return y.CompareTo(x); } } // ... var Dict = new SortedDictionary(new DescendingComparer()); 
  3. Utilice SortedList lugar. El rendimiento no es tan bueno como el del diccionario (O (n) en lugar de O (logn)), pero tiene acceso aleatorio en los elementos como en las matrices. Cuando use el IDictionary-Interface genérico, no tendrá que cambiar el rest de su código.

Editar :: iterar en listas ordenadas

¡Solo tienes acceso a los elementos por índice!

 var Rand = new Random(); var Dict = new SortedList(); for (int i = 1; i <= 10; ++i) { var newItem = Rand.Next(1, 100); Dict.Add(newItem, (newItem * newItem).ToString()); } // Reverse for loop (forr + tab) for (int i = Dict.Count - 1; i >= 0; --i) { Console.WriteLine("{0} -> {1}", Dict.Keys[i], Dict.Values[i]); } 

La forma más fácil de definir el SortedDictionary en el orden inverso para empezar es proporcionarle un IComparer que se ordena en orden inverso al normal.

Aquí hay un código de MiscUtil que puede hacerte más fácil:

 using System.Collections.Generic; namespace MiscUtil.Collections { ///  /// Implementation of IComparer{T} based on another one; /// this simply reverses the original comparison. ///  ///  public sealed class ReverseComparer : IComparer { readonly IComparer originalComparer; ///  /// Returns the original comparer; this can be useful /// to avoid multiple reversals. ///  public IComparer OriginalComparer { get { return originalComparer; } } ///  /// Creates a new reversing comparer. ///  /// The original comparer to /// use for comparisons. public ReverseComparer(IComparer original) { if (original == null) { throw new ArgumentNullException("original"); } this.originalComparer = original; } ///  /// Returns the result of comparing the specified /// values using the original /// comparer, but reversing the order of comparison. ///  public int Compare(T x, T y) { return originalComparer.Compare(y, x); } } } 

Luego usarías:

 var dict = new SortedDictionary (new ReverseComparer(StringComparer.InvariantCulture)); 

(o el tipo que estabas usando).

Si solo desea iterar en una dirección, esto será más eficiente que revertir el orden posteriormente.

También hay un enfoque muy simple si se trata de valores numéricos como la clave que es simplemente negarlos cuando se crea el diccionario.

Cree brevemente un diccionario ordenado invertido en una línea .

 var dict = new SortedDictionary(Comparer.Create((x, y) => y.CompareTo(x))); 

Hay una manera de crear un IComparer usando System.Collections.Generic.Comparer . Simplemente pase un IComparision a su método Create para construir un IComparer .

 var dict = new SortedDictionary( Comparer.Create( delegate(int x, int y) { return y.CompareTo(x); } ) ); 

Puede usar una expresión lambda / función / método local para reemplazar al delegado si su significado es (TKey, TKey) => int .

Si usa .NET 3.5, puede usar el método de extensión OrderByDescending:

  var dictionary = new SortedDictionary(); dictionary.Add(1, "One"); dictionary.Add(3, "Three"); dictionary.Add(2, "Two"); dictionary.Add(4, "Four"); var q = dictionary.OrderByDescending(kvp => kvp.Key); foreach (var item in q) { Console.WriteLine(item.Key + " , " + item.Value); }