Question

Est-il possible que je peux itérer en arrière (en sens inverse) par un SortedDictionary en c #?

Ou est-il un moyen de définir la SortedDictionary dans l'ordre décroissant pour commencer?

Était-ce utile?

La solution

Le SortedDictionary lui-même ne prend pas en charge l'itération vers l'arrière, mais vous avez plusieurs possibilités pour obtenir le même effet.

  1. Utilisation .Reverse-méthode (Linq). (Cela devra pré-calculer l'ensemble de sortie de dictionnaire, mais est la solution la plus simple)

    var Rand = new Random();
    
    var Dict = new SortedDictionary<int, string>();
    
    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. Faites le tri de dictionnaire dans l'ordre décroissant.

    class DescendingComparer<T> : IComparer<T> where T : IComparable<T> {
        public int Compare(T x, T y) {
            return y.CompareTo(x);
        }
    }
    
    // ...
    
    var Dict = new SortedDictionary<int, string>(new DescendingComparer<int>());
    
  3. Utilisez SortedList<TKey, TValue> à la place. Les performances ne sont pas aussi bon que le dictionnaire (O (n) au lieu de O (log n)), mais vous avez accès aléatoire aux éléments tels que dans des tableaux. Lorsque vous utilisez le IDictionary-Interface générique, vous ne devrez pas changer le reste de votre code.

Modifier :: Itère sur SortedLists

Vous accédez simplement les éléments par index!

var Rand = new Random();


var Dict = new SortedList<int, string>();

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

Autres conseils

La meilleure façon de définir la SortedDictionary dans l'ordre inverse pour commencer est de lui fournir une IComparer<TKey> qui trie dans l'ordre inverse à la normale.

Voici un code de MiscUtil qui pourrait rendre plus facile pour vous que:

using System.Collections.Generic;

namespace MiscUtil.Collections
{
    /// <summary>
    /// Implementation of IComparer{T} based on another one;
    /// this simply reverses the original comparison.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public sealed class ReverseComparer<T> : IComparer<T>
    {
        readonly IComparer<T> originalComparer;

        /// <summary>
        /// Returns the original comparer; this can be useful
        /// to avoid multiple reversals.
        /// </summary>
        public IComparer<T> OriginalComparer
        {
            get { return originalComparer; }
        }

        /// <summary>
        /// Creates a new reversing comparer.
        /// </summary>
        /// <param name="original">The original comparer to 
        /// use for comparisons.</param>
        public ReverseComparer(IComparer<T> original)
        {
            if (original == null)
            { 
                throw new ArgumentNullException("original");
            }
            this.originalComparer = original;
        }

        /// <summary>
        /// Returns the result of comparing the specified
        /// values using the original
        /// comparer, but reversing the order of comparison.
        /// </summary>
        public int Compare(T x, T y)
        {
            return originalComparer.Compare(y, x);
        }
    }
}

Vous souhaitez ensuite utiliser:

var dict = new SortedDictionary<string, int>
     (new ReverseComparer<string>(StringComparer.InvariantCulture));

(ou quel que soit le type que vous utilisez).

Si vous ne voulez jamais itérer dans une direction, ce sera plus efficace que d'inverser l'ordre par la suite.

Il y a aussi une approche très simple si vous avez affaire à des valeurs numériques comme la clé qui est de les annuler simplement lorsque vous créez le dictionnaire.

créer brièvement un dictionnaire trié inversé en une ligne .

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

Il y a un moyen de créer un IComparer<T> en utilisant System.Collections.Generic.Comparer<T>. Il suffit de passer un délégué IComparision<T> à sa méthode Create pour construire un IComparer<T>.

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

Vous pouvez utiliser un expression lambda / fonction locale / méthode pour remplacer le délégué si leur signification sont (TKey, TKey) => int.

Si vous utilisez .NET 3.5, vous pouvez utiliser la méthode d'extension OrderByDescending:

        var dictionary = new SortedDictionary<int, string>();
        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);
        }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top