8

I have a SortedDictionary as defined like this:

SortedDictionary<TPriority, Queue<TValue>> dict;

But I want to maintain the dict in reverse order. I assume I need set the Comparer, but what comparer do I use for a generic TPriority? Note that TPriority implements IComparable.

mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • possible duplicate of [Reverse Sorted Dictionary in .NET](http://stackoverflow.com/questions/931891/reverse-sorted-dictionary-in-net) – nawfal Jun 15 '14 at 10:28

3 Answers3

16

You can create a reverse comparer quite easily:

public sealed class ReverseComparer<T> : IComparer<T> {
    private readonly IComparer<T> inner;
    public ReverseComparer() : this(null) { }
    public ReverseComparer(IComparer<T> inner) {
        this.inner = inner ?? Comparer<T>.Default;
    }
    int IComparer<T>.Compare(T x, T y) { return inner.Compare(y, x); }
}

Now pass that into the constructor for the dictionary:

var dict = new SortedDictionary<TPriority, Queue<TValue>>(
                 new ReverseComparer<TPriority>());
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Why pass `null` and then check for it, when you could have passed in `Comparer.Default` in the first place? – mpen May 06 '10 at 21:46
  • Tasty use of `sealed`, `readonly` and the null-coalescing operator. – Jesse C. Slicer May 06 '10 at 21:48
  • @Mark - well, I could have, but then I really should have added a `NullArgumentException` check a well, etc. – Marc Gravell May 06 '10 at 23:28
  • 1
    Ohh... in case they explicitly pass a null object to the c'tor. That makes sense then. – mpen May 07 '10 at 00:14
  • Nice. is there any advantage/disadvantage to having two constructors (one which calls the other) as listed here vs simply having one constructor which takes an optional parameter (with default value null)? – Adam Dec 15 '11 at 10:31
  • @Adam only that not everyone has C# 4.0 ;p – Marc Gravell Dec 15 '11 at 12:16
  • 1
    @Mark Ah! I actually work in vb.net not C# and wasn't aware the optioanl parameters were not possible in 3.5 in C# – Adam Dec 15 '11 at 14:09
1

If you can use LINQ, you can just do:

dict.Keys.Reverse();

This yields the keys of the collection in reverse order.

EDIT: The SortedDictionary class is assigned a IComparer<T> when it is constructed, and this cannot be changed after the fact. However, you can create a new SortedDictionary<T> from the original:

class ReverseComparer<T> : IComparer<T>  {
   private readonly m_InnerComparer = new Comparer<T>.Default;

   public ReverseComparer( IComparer<T> inner )   {
      m_InnerComparer = inner; }

   public int Compare( T first, T second )  {
       return -m_InnerComparer.Compare( first, second );  }
}

var reverseDict = new SortedDictionary<TPriority, Queue<TValue>>( dict, 
                          new ReverseComparer( Comparer<TPriority>.Default ) );
LBushkin
  • 129,300
  • 32
  • 216
  • 265
  • Well, I didn't mean that I wanted the keys in reverse order, I meant that I want to maintain the dict in reverse order so that when I iterate over it, it will always be in descending order... – mpen May 06 '10 at 21:27
  • @Mark:Perhaps then you should not have said that you wanted the keys in reverse order. You should edit your question to make sure it is clear for the benefit of those who search in the future. – Tom Cabanski May 06 '10 at 21:33
  • @Tom: I didn't say that I "wanted the keys in the reverse order". I said I wanted to sort the keys in reverse order, thereby sorting the dict. I said "keys" to distinguish from sorting the queues/TValues, but I understand where the confusion came from. Amended. – mpen May 06 '10 at 21:39
1

I ended up just adding this to my class, as it's the shortest and simplest:

private class ReverseComparer : IComparer<TPriority>
{
    public int Compare(TPriority x, TPriority y) { return y.CompareTo(x); }
}

And then initialize the dict like so:

dict = new SortedDictionary<TPriority, Queue<TValue>>(new ReverseComparer());
mpen
  • 272,448
  • 266
  • 850
  • 1,236