简体   繁体   中英

C# iterating over Dictionary by arbitrary order

I have a Dictionary<string, List<Object>> . I loop through the keys of the dictionary and display the values grouped by the key. I know about SortedDictionary and OrderedDictionary but how do you sort a dictionary by a predefined order, not just alphabetically ascending/descending?

Assume that I know all possible keys in my dictionary will exist in the below list and want the dictionary to be sorted in the following order:

  1. Quick
  2. Brown
  3. Fox
  4. Jumped
  5. Over

How do I go about doing this?

You don't sort a Dictionary<,> at all. However, if you want to iterate over the entries (or keys) in a particular order, you can use LINQ's OrderBy - and to iterate a known set of values in that order, you can just have the ordered set somewhere else. For example:

string[] orderedKeys = { "Quick", "Brown", "Fox", "Jumped", "Over" };
var orderedPairs = dictionary.OrderBy(pair => orderedKeys.IndexOf(pair.Key));
foreach (var pair in orderedPairs)
{
    // Use pair.Key and pair.Value here
}

If you want to always access the key/value pairs in that order and benefit from a SortedDictionary you need to implement IComparer<string> and pass that to your dictionary constructor. The easiest way to implement it is to have a static array of strings in the order you want, then compare the indexes of the two strings:

public class MyStringComparer : IComparer<string>
{

   static string[] StringsInOrder = new [] { "Quick", "Brown", "Fox", "Jumped", "Over" };
   public int Compare(string s1, string s2)
    {
        // find the indexes of the strings in the desired sort order
        int i1 = Array.IndexOf(StringsInOrder, s1);
        int i2 = Array.IndexOf(StringsInOrder, s2);

        if(i1 < 0)
            // put at the end in alpha order
            if(i2 < 0)
                return s1.CompareTo(s2);
            else  
                // send s1 to the end
                return 1;  
        else
           if(i2 < 0)
               // send s2 to the end
               return -1;
           else  
                // compare the indices in the array
                return i1.CompareTo(i2);
    }
}

usage:

var d = new SortedDictionary<string, string> (new MyStringComparer());

If you want to keep a normal dictionary for other purposes (fast lookups, etc.) but just sort the keys occasionally then using Linq as Jon suggests may be better overall.

Just a thought. Could you add a "SortKey" property to your object & use LINQ to obtain a sorted list?

One option would be to iterate the list of keys and access the values in your dictionary.

string[] orderedKeys = { "Quick", "Brown", "Fox", "Jumped", "Over" };
foreach (var key in orderedKeys)
{
    List<object> values;
    if (dictionary.TryGetValue(key, out values))
    {
        // Here you have the key and the list of values
    }
    else
    {
        // The key was not in the dictionary.
    }
}

Note that this will not give you any entries in the dictionary that do not have a corresponding key in the list. It would also potentially give you entries twice if the list has duplicates.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM