'Sort C# Dictionary by a custom array/list, and output reordered dictionary Values as list

There are a few similar questions, but unfortunately none I've found that offer the answer I require. Help is appreciated.

First Question

I have a dictionary lets say like the below (simplified for example):

IDictionary<string, string> Beatles = new Dictionary<string, string>();
Beatles.Add("Singer", "John");
Beatles.Add("Drummer", "Ringo");
Beatles.Add("Guitar", "Paul");
Beatles.Add("Bass", "George");

Is it possible to reorder the dictionary based on something like a string array or a list below (EDIT - and output a List with just the reordered Values, as someone clarified Dictionaries don't have order):

string[] reorderList = {"Guitar","Bass","Singer","Drummer"};

EDIT - I want the output to be a List containing this order: "Paul", "George", "John", "Ringo"



Secondary Question

Let's say I don't include one of the Dictionary items in my ordering string, like this:

string[] locations = {"Guitar","Singer","Drummer"};

I want all missing items (in this case just "Drums") to be automatically added to the end. Is that possible?



Solution 1:[1]

Here's a quick extension that will return what you are asking for:

    public static class DictionaryExtension
    {
        public static List<T> CustomSort<TK, T>(this IDictionary<TK, T> src, TK[] sortList)
        {
            // items in the sortList
            var output = (from key in sortList where src.ContainsKey(key) select src[key]).ToList();

            // remaining "other" items
            output.AddRange((from item in src where !sortList.Contains(item.Key) select item.Value).OrderBy(o => o));

            return output;
        }
    }

Note: It isn't checking for IComparable so YMMV. And if you have duplicate keys in the reorderList you will get duplicate values in the results.

Solution 2:[2]

That's a very interesting problem. First of all as everyone suggested, you cannot reorder Dictionary. However, you can achieve your desired output by running following piece of code

var pass1 = reorderList.Select(x => Beatles.ContainsKey(x) ? Beatles[x] : null).Where(x => x != null); //Adds desired ordered list of Dictionary values to the list
var result = pass1.Union(Beatles.Values.Except(pass1)).ToList(); //Appends remaining values, if any, to list

Variable result will have your desired output.

Update

Updated above code to take care of invalid values.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2