【问题标题】:How can I sort (Custom Sort) list of Dictionary entry by value如何按值对字典条目的(自定义排序)列表进行排序
【发布时间】:2016-08-09 16:29:42
【问题描述】:

我的哈希表包含 (key, Values[])

例如:

myHashtable[keys, Values[]]

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

其中值1; value2、value3、value4、value5如下。

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"]

我想订购这个dictionaryEntry 列表值,其中Identity 具有“C”值,然后是“A”,然后是“S”,然后是“”

排序后的结果应该如下。

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 = ""

这是我的尝试。

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);

如何对 combineResult 进行排序以提供上述自定义排序字典条目列表?

非常感谢任何帮助。 谢谢你

【问题讨论】:

  • 你的case (实际上)什么都不做,因为在它变成字典后,排序就消失了。如果我需要维护排序,我可能会提供一个带有自定义比较器的SortedDictionary 实例。如果您只想对枚举的输出进行排序,请在 OrderByDescending 中执行此操作。

标签: c# list dictionary ordereddictionary icomparer


【解决方案1】:

当使用哈希表实现 Dictionary 数据结构时,为了实现分摊的 O(1) 插入/删除/更新操作,数据是未排序的。另一方面,当 Dictionary 使用平衡树实现时,操作会稍慢 O(logn),但可以以排序方式(通过键)枚举。例如,C# 字典实现未排序,C++ 映射已排序(基于红黑树)
鉴于上述情况(您无法在字典中对数据进行排序),您可以将字典保存为列表/数组,然后按您想要的任何比较器进行排序。

这是一个字典和自定义比较器的示例,您可以在其中获取字典中的值,按自定义比较器中的逻辑排序:

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

您还可以使用 SortedDictionary(如 @Clockwork-Muse 建议的那样)并传递与上述示例类似的 CustomComparer。这实际上取决于您的要求。如果您需要操作保持快速并且只需要为报告排序的值,那么只需在需要值时进行排序(如我的示例中所示)。如果您要大量访问已排序的值,那么首先将它们保持排序可能是有意义的。

【讨论】:

  • 谢谢Itsik!如果输入来自带有键和值的哈希表,您将如何将输入插入 Dictionary unsortedDictionary?上面示例中的 Dictionary 在哪里?
  • DictionaryEntry 包含一个用于键和值的object,因此您可以将它们转换为dictionary.Add((int)dictionaryEntry.Key, (Data)dictionaryEntry.Value)。您开始使用 Hashtable 是否有特定原因?而不是通用字典?
  • 还不确定程序为什么使用 Hashtable。但这是我尝试将输入(哈希表结果)插入到 unsortedDictionary 的方式。但是,我无法将字典“键”值放入 unsortedDictionary。 [Dictionary&lt;int, Data&gt; unsortedDictionary = new Dictionary&lt;int, Data&gt;(); foreach (DictionaryEntry entry in HashtableResult) { unsortedDictionary.Add((int)entry.Key, (Data)entry.Value); } var customSortedValues = unsortedDictionary.Values.OrderBy(item =&gt; item, new CustomerComparer()).ToArray();]
  • 因此,使用上述输入, unsortedDitrionary 的值将变为如下。 [unsortedDictionary.Add(entry.key, (Data)entry.Value) would have a collection of unsortedDictionary[0]: {[Key1, Data1]} ; unsortedDictionary[1]: {[key2, Data2]} ] 等等。排序后,我会丢失键值,它只会成为数据列表。
  • 那是因为在我的示例中,我只是对值进行了排序。我更新了示例以保留 KeyValuePairs。
猜你喜欢
  • 1970-01-01
  • 2018-08-26
  • 2011-02-22
  • 2010-09-09
相关资源
最近更新 更多