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.