views:

162

answers:

2

What is the 'best' way to sort (or iterate) over a StringDictionary in order of Value (not Key)

E.g. Key - Value

  • 1 - X label
  • 2 - A label
  • 3 - Other label

would give

  • 2 - A label
  • 3 - Other label
  • 1 - X label

EDIT - I meant to say "using .NET 2.0 features". Sorry, me bad...

+9  A: 

Use LINQ:

var items = from k in d.Keys
                    orderby d[k] ascending
                    select k;

If you are restricted to C# 2.0 features, use this:

    IDictionary<string, string> d = new Dictionary<string, string>();
    d["1"] = "X label";
    d["2"] = "A label";
    d["3"] = "Other Label";

    List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(d);
    myList.Sort(
        delegate(KeyValuePair<string, string> a,
        KeyValuePair<string, string> b)
        {
            return a.Value.CompareTo(b.Value);
        }
    );

Note: If you are using a StringDictionary instead of Dictionary, check out Anthony's solution.

dcp
46 seconds.....
Will
Actually this will only sort the values, not the associated keys as well.
SWeko
@Sweko it selects keys sorted by value (d[k] = value).
Will
doesn't work. "Could not find an implementation of the query pattern for source type 'System.Collections.ICollection'. 'OrderBy' not found"
Jamiec
You and Will are just tooo fast! Or maybe I should properly edit my question before clicking... Sorry! +1 ing both of you anyway.
Ryan
@Jamiec - Not sure what you mean, it works fine for me on .Net 3.5. Of course, OP has now said we can't use it :(.
dcp
@Jamiec you scared me there for a moment. Checked and verified working. You need "using System.Linq;".
Will
@Ryan 2.0? Pre-Linq? The thought frightens and confuses me.
Will
@Will, @dcp, he's using `StringDictionary`, not `Dictionary`. Hence Jamiec's error message (even in 3.5). This answer would actually work (in 3.5) by saying `from string k in d.Keys`.
Anthony Pegram
Aye, 'fraid so. Targeting vanilla install of SharePoint 2007 and corporates can move at a glacial speed. Just look at the curse of the un-dead IE6.
Ryan
EGADS! I even read the question wrong! I'll have to delete this question, all answers, and destroy all users in order to cover this one up...
Will
@Will - I checked with a StringDictionary on 3.5 just out of pure interest, and your solution does work as long as you use `from string k in ...`
Jamiec
+3  A: 

Using the StringDictionary class, here is a method to use LINQ's OrderBy. Assumes you have .NET 3.5.

var sortedDictionary = dictionary.Cast<DictionaryEntry>().OrderBy(pair => pair.Value);

Using 2.0, it's a bit trickier. Here's an approach using a Comparison delegate.

StringDictionary dictionary = new StringDictionary();
dictionary.Add("1", "One");
dictionary.Add("2", "Two");
dictionary.Add("3", "Three");

DictionaryEntry[] sortedDictionary = new DictionaryEntry[dictionary.Count];
dictionary.CopyTo(sortedDictionary, 0);
Comparison<DictionaryEntry> comparison = new Comparison<DictionaryEntry>(delegate (DictionaryEntry obj1, DictionaryEntry obj2) { return ((string)obj1.Value).CompareTo((string)obj2.Value); });
Array.Sort(sortedDictionary, comparison);

So the actual sort would be in the sortedDictionary array.

Anthony Pegram
+1: You may need special handling when obj1 != null (unless you can guarentee otherwise).
Binary Worrier
@Binary, that may be worth exploring, certainly. The more likely scenario is that obj1.Value could be null. So absolutely add checks as needed.
Anthony Pegram