How can I sort (Custom Sort) list of Dictionary entry by value

被刻印的时光 ゝ 提交于 2020-01-13 14:04:38

问题


My hashtable contains (key, Values[])

e.g:

myHashtable[keys, Values[]]

myHashtable.Add[1, Value1];
myHashtable.Add[2, Value2];
myHashtable.Add[3, Value3]; 
myHashtable.Add[4, Value4];
myHashtable.Add[5, Value5];

Where Value1; Value2, value3, value4, and value5 is as follows.

Value1[name = "Smith"]
Value1[Title= "Mr"]
Value1[Salary = 1000]
Value1[Identity = "S"]

Value2[name = "Peter"]
Value2[Title= "Mr"]
Value2[Salary = 1000]
Value2[Identity = "A"]


Value3[name = "Tom"]
Value3[Title= "Mr"]
Value3[Salary = 1000]
Value3[Identity = "C"]


Value4[name = "Marry"]
Value4[Title= "Ms"]
Value4[Salary = 1000]
Value4[Identity = ""]

Value5[name = "Sam"]
Value5[Title= "Mr"]
Value5[Salary = 1000]
Value5[Identity = "C"]

I want to order this dictionaryEntry list values where Identity with "C" values first then "A" then "S" then ""

After sorting the Result should be like as follows.

myHashtable.Add[3, Value3]; // Value3.Identity = "C"
myHashtable.Add[5, Value5]; // Value5.Identity = "C"
myHashtable.Add[2, Value2]; // Value2.Identity = "A"
myHashtable.Add[1, Value1]; // Value1.Identity = "S"
myHashtable.Add[4, Value4]; // Value4.Identity = ""

Here is my attempt.

var result1 = new List<DictionaryEntry>(hashtable.Count);
var result2 = new List<DictionaryEntry>(hashtable.Count);
var result3 = new List<DictionaryEntry>(hashtable.Count);                 
var result4 = new List<DictionaryEntry>(hashtable.Count);


var result = new List<DictionaryEntry>(hashtable.Count);

foreach (DictionaryEntry entry in hashtable)
   {
        result.Add(entry);
   }


                foreach (DictionaryEntry dictionaryEntry in result)
                {
                    var t2 = dictionaryEntry.Value;

                    switch (t2.Identity)
                    {
                        case "C":
                            result1.Add(dictionaryEntry);
                            break;
                        case "A":
                            result2.Add(dictionaryEntry);
                            break;
                        case "S":
                            result3.Add(dictionaryEntry);
                            break;
                        case "":
                            result4.Add(dictionaryEntry);
                            break;
                        default:
                            break;
                    }
                }
                result1.ToList();
                result2.ToList();
                result3.ToList();


                var combinedResult = result1.Union(result2)
                    .Union(result3)
                    .Union(result4)
                    .ToDictionary(k => k.Key, v => v.Value).OrderByDescending(v => v.Value);

How can I sort combinedResult to give me the above custom sorted dictionary entry list?

Any help is greatly appriciated. Thank You


回答1:


When a Dictionary data structure is implemented with a hashtable, in order to achieve the amortized O(1) insert/delete/update operations the data is unsorted. On the other hand, when the Dictionary is implemented with a balanced tree, the operations are a bit slower O(logn) but they can be enumerated in sorted way (by the key). For example, C# dictionary implementation is unsorted, and a C++ map is sorted (based on a red-black tree)
Given the above (you cannot have the data sorted however you want in the dictionary), What you can do is save the dictionary as a List/Array, and then sort by whichever comparator you want.

Here is an example of a Dictionary and a custom comparer, where you can get the values in the dictionary sorted by the logic in the custom comparer:

public class Data
{
    public string Name { get; set; }
    public string Identity { get; set; }
}

public class CustomerComparer : IComparer<KeyValuePair<int, Data>>
{
    private List<string> orderedLetters = new List<string>() { "C", "A", "S" };

    public int Compare(KeyValuePair<int, Data> str1, KeyValuePair<int, Data> str2)
    {
        return orderedLetters.IndexOf(str1.Value.Identity) - orderedLetters.IndexOf(str2.Value.Identity);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Data value1 = new Data { Name = "Name1", Identity = "S" };
        Data value2 = new Data { Name = "Name2", Identity = "A" };
        Data value3 = new Data { Name = "Name3", Identity = "C" };
        Data value4 = new Data { Name = "Name4", Identity = "C" };

        Dictionary<int, Data> unsortedDictionary = new Dictionary<int, Data>();
        unsortedDictionary.Add(1, value1);
        unsortedDictionary.Add(2, value2);
        unsortedDictionary.Add(3, value3);
        unsortedDictionary.Add(4, value4);

        var customSortedValues = unsortedDictionary.Values.OrderBy(item => item, new CustomerComparer()).ToArray();

        for (int i=0; i < customSortedValues.Length; i++)
        {
            var kvp = customSortedValues[i];
            Console.WriteLine("{0}: {1}=(Name={2}, Identity={3})", i, kvp.Key, kvp.Value.Name, kvp.Value.Identity);
        }
    }
}
//Output is:  
//0: Name3=C
//1: Name4=C
//2: Name2=A
//3: Name1=S

You can also use a SortedDictionary (as @Clockwork-Muse suggests) and pass a similar CustomComparer as in the above example. This really depends on what your requirements are. If you need the operations to stay fast and only need the values sorted for, perhaps, reporting, then just sort when the values are needed (as in my example). If you will be accessing the sorted values alot, it may make sense to just keep them sorted in the first place.



来源:https://stackoverflow.com/questions/36685446/how-can-i-sort-custom-sort-list-of-dictionary-entry-by-value

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!