-2

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?

JackNapier
  • 318
  • 4
  • 14
  • Every question about "sort a dictionary" should have informed you that dictionaries do not support order... Could you please clarify what you expect to happen as result of "sorting" a dictionary? – Alexei Levenkov Mar 24 '22 at 22:25
  • Yes, of course *insert 'Anything is possible' toystory meme* But you'll need to create your own custom method to do that and keep in mind that C# Dictionary can't be ordered. Try it yourself, it will be fun, here are some easy steps you could use 1. Create an new empty SortedDictionary (or List) 2. Do a foreach on reorderList 3. If the reorderList value exist in Beatles -> copy that entry to your new List 3. Find every Beatles that is not included in new List -> copy them to the new List – Daniel Dutra Mar 24 '22 at 22:29
  • Alexei, I require the Values of a dictionary to be turned into a List, based off the Keys being ordered by my string Array. The final result for Q1 would be this List: {"Paul", "George", "John", "Ringo}". (I'll edit the question to clarify). – JackNapier Mar 24 '22 at 22:31
  • Is it possible you’d be better off grouping them into a class or similar that contains all the associated data for each item (potentially even including a numerical priority for sorting)? Then you could add those class instances to a list and use one of various available methods to sort that list in different ways or create sorted copies. You could still also store the class instances in a dictionary if desired. – Sven Viking Mar 24 '22 at 22:49

2 Answers2

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.

0

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.

Gaurav Mathur
  • 804
  • 5
  • 14