Home > Back-end >  Sort C# Dictionary by a custom array/list, and output reordered dictionary Values as list
Sort C# Dictionary by a custom array/list, and output reordered dictionary Values as list

Time:03-25

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?

CodePudding user response:

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.

CodePudding user response:

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.

  • Related