Reverse Sorted Dictionary in. NET

C’è un modo per iterare all’indietro (al contrario) attraverso un SortedDictionary in c #?

O c’è un modo per definire il SortedDictionary in ordine decrescente per cominciare?

Lo stesso SortedDictionary non supporta l’iterazione arretrata, ma hai diverse possibilità per ottenere lo stesso effetto.

  1. Usa. .Reverse (Linq). (Questo dovrà pre-calcolare l’intero output del dizionario ma è la soluzione più semplice)

     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. Rendi il dizionario in ordine decrescente.

     class DescendingComparer : IComparer where T : IComparable { public int Compare(T x, T y) { return y.CompareTo(x); } } // ... var Dict = new SortedDictionary(new DescendingComparer()); 
  3. Utilizzare invece SortedList . Le prestazioni non sono buone come quelle del dizionario (O (n) invece di O (logn)), ma si ha accesso casuale agli elementi come negli array. Quando si utilizza l’interfaccia IDictionary generica, non sarà necessario modificare il resto del codice.

Modifica :: Iterating su SortedLists

Basta accedere agli elementi per indice!

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

Il modo più semplice per definire SortedDictionary nell’ordine inverso per iniziare è fornirgli un IComparer che ordina nell’ordine inverso alla normalità.

Ecco un codice da MiscUtil che potrebbe renderlo più facile per te:

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

Dovresti quindi usare:

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

(o qualsiasi altro tipo stavi usando).

Se si desidera solo ripetere l’iterazione in una direzione, ciò sarà più efficiente rispetto all’inversione dell’ordine successivo.

C’è anche un approccio molto semplice se si ha a che fare con valori numerici come la chiave che consiste semplicemente nel negarli quando si crea il dizionario.

Crea brevemente un dizionario ordinato invertito in una riga .

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

C’è un modo per creare un IComparer usando System.Collections.Generic.Comparer . Basta passare un IComparision al suo metodo Create per creare un IComparision IComparer .

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

È ansible utilizzare un’espressione lambda / funzione / metodo locale per sostituire il delegato se il loro significato è (TKey, TKey) => int .

Se si utilizza .NET 3.5, è ansible utilizzare il metodo di estensione 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); }