5

I have the following dictionary:

SortedDictionary<int, string> dictionary = new SortedDictionary<int, string>();
dictionary.add(2007, "test1");
dictionary.add(2008, "test2");
dictionary.add(2009, "test3");
dictionary.add(2010, "test4");
dictionary.add(2011, "test5");
dictionary.add(2012, "test6");

I'd like to reverse the order of the elements so that when I display the items on the screen, I can start with 2012. I'd like to reassign the reversed dictionary back to the variable dictionary if possible.

I tried dictionary.Reverse but that doesn't seem to be working as easily as I thought.

nawfal
  • 70,104
  • 56
  • 326
  • 368
Adam Levitt
  • 10,316
  • 26
  • 84
  • 145
  • 1
    Create a new `SortedDictionary` with a reversed comparer. – CodesInChaos Nov 10 '12 at 15:20
  • Could you give me an example of this please? It sounds like it's what I'm looking for. – Adam Levitt Nov 10 '12 at 15:20
  • 1
    http://stackoverflow.com/questions/10539525/do-i-need-2-comparert-for-sorting-in-both-directions – CodesInChaos Nov 10 '12 at 15:21
  • There is no "Sort" method on the dictionary unfortunately. I had already looked for it. ... Also, I'd like to not write extra code or classes if possible. This seems like something that should be easily done with LINQ. – Adam Levitt Nov 10 '12 at 15:23
  • 3
    1) You don't need a `Sort` method. You just need the same comparer approach as that other question 2) No LINQ won't help you. You need a custom comparer. LINQ will give you an `IEnumerable>` not a `SortedDictionary`. – CodesInChaos Nov 10 '12 at 15:26
  • The `Reverse` extension method doesn't change your dictionary. It simply foreach-es through it and then yields the elements in opposite order. You could use it like `foreach (var intStringPair in dictionary.Reverse()) { SomehowDisplay(intStringPair); }` But also see the answers. – Jeppe Stig Nielsen Nov 10 '12 at 17:37

2 Answers2

19

If you're using the newest version of the framework, .NET 4.5 (Visual Studio 2012), you can do it very easily with Comparer<>.Create. It's like this:

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

Note the order of x and y in the lambda.

Jeppe Stig Nielsen
  • 60,409
  • 11
  • 110
  • 181
7

You can give SortedDictionary an IComparer<TKey> on construction. You just need to provide one which reverses the order. For example:

public sealed class ReverseComparer<T> : IComparer<T>
{
    private readonly IComparer<T> original;

    public ReverseComparer(IComparer<T> original)
    {
        // TODO: Validation
        this.original = original;
    }

    public int Compare(T left, T right)
    {
        return original.Compare(right, left);
    }
}

Then:

var dictionary = new SortedDictionary<int, string>(
       new ReverseComparer<int>(Comparer<int>.Default));
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks for the reply. Using this, how am I getting the original dictionary into the newly created one? – Adam Levitt Nov 10 '12 at 15:26
  • @AdamLevitt: It's not clear what you're trying to do. This would be *instead* of the original code. Just add the values into this dictionary. Do you actually need the dictionary in its original order as well? – Jon Skeet Nov 10 '12 at 15:28
  • 1
    @AdamLevitt You don't. The `Comparer` property of `SortedDictionary` is read-only, and can't be changed after construction. – CodesInChaos Nov 10 '12 at 15:28
  • @Jon Skeet - Thanks for the help. So, I create the dictionary as displayed above. Once I have the entries in there, I just want to do the reverse and I'll never need the original again. Once I put the values into this dictionary, do I need to make another call to actually do the reverse action? – Adam Levitt Nov 10 '12 at 15:30
  • @AdamLevitt: Why do you want to reverse it *afterwards*? The point of the code in my answer is that you create the dictionary so that the entries will *always* be in descending order, automatically, with no further action required. – Jon Skeet Nov 10 '12 at 15:32
  • @Jon Skeet - This did it! I understand completely. However, the constructor should be modified in your answer to say "this.original = original"... and thanks! – Adam Levitt Nov 10 '12 at 15:34
  • @AdamLevitt: Yup, that was a dumb typo. Glad it's working for you. – Jon Skeet Nov 10 '12 at 15:40
  • @AdamLevitt In .NET 4.5 you can even do it without writing the class yourself (see my alternative answer). – Jeppe Stig Nielsen Nov 10 '12 at 17:30
  • You can do something like this : var sortedDict=new SortedDictionary(); sortedDict.OrderByDescending(x=>x.Value); – roney Apr 14 '17 at 23:02
  • @robert: No, calling OrderByDescending and ignoring the return value won't do anything. – Jon Skeet Apr 15 '17 at 06:45