【问题标题】:C# Sort a Dictionary<string,float> in descending order by value - without Linq in .net 2.0C# 按值降序对 Dictionary<string,float> 进行排序 - .net 2.0 中没有 Linq
【发布时间】:2019-03-31 18:17:13
【问题描述】:

如何在不使用 Linq 的情况下,仅使用 .net 2.0 中提供的功能,按值降序对通用字典(字符串、浮点数)进行排序。

请注意,我不希望自己对值进行排序 - 键需要以某种方式连接到值。 (否则,我会问如何对列表进行排序,对吧?)

【问题讨论】:

  • Soooooo,您确实意识到对字典进行排序没有任何意义?我猜你最后可能想要一个排序的浮点数组?
  • 请展示你目前的成果
  • 也许你可以从 Linq.OrderBy() implementation in the .Net source code 的方法中得到启发(按照代码流向下一点。这是 QuickSort 部分)。
  • @ina 您是否要对字典进行适当的排序?还是将字典的内容放入存储的新对象/数据结构中? 我问,因为前者是不可能的,后者是可能的。
  • 令人惊讶的是,即使 .NET 2.0 也有“SortedDictionary”,这将允许在 (但不是值)上使用自定义比较器以使条目按降序排序,它也有 OrderedDictionary,这是一种非泛型类型,允许以您喜欢的任何顺序插入对,但我没有看到一个很好的泛型解决方案,它允许按值排序(这似乎是一件很奇怪的事情)

标签: c# .net-2.0


【解决方案1】:

如果你只想要一个排序的浮点数组,这符合 .net 2

var dict = new Dictionary<string,float>();
var values = new float[dict.Count];
dict.Values.CopyTo(values, 0);
Array.Sort(values);
Array.Reverse(values);

或者

private class SortDesc : IComparer
{
   int IComparer.Compare(object a, object b)
   {
      var c1 = (KeyValuePair<string, float>)a;
      var c2 = (KeyValuePair<string, float>)b;
      if (c1.Value > c2.Value)
         return -1;
      return c1.Value < c2.Value ? 1 : 0;
   }
}

用法

var dict = new Dictionary<string, float>();
var result = new KeyValuePair<string, float>[dict.Count];
((ICollection<KeyValuePair<string, float>>)dict).CopyTo(result, 0);

var sortDesc = new SortDesc();      
Array.Sort(result, sortDesc);

免责声明:完全未经测试

我觉得我有责任指出,.Net 2.0 不再受支持且不再提供

【讨论】:

  • 这不对字典进行排序...?
  • @rufus,确实它没有:) 现在添加第二种情况,但是我一直不得不测试.net 2:/
  • 拍脑袋,我在这方面做得很辛苦,制作表情包之类的东西
  • 所有准备工作都可以替换为((ICollection&lt;KeyValuePair&lt;string, float&gt;&gt;)dict).CopyTo(result, 0);
  • 这看起来很荒谬,但 Unity / Mono 仍然在 .net 2.0 / 子集上
【解决方案2】:

仅使用 .net 2.0 中提供的功能

假设您已经安装了 Visual Studio 的多目标包,您应该能够在创建项目时以特定框架为目标。您还可以通过项目的属性页更改目标框架。

如果您还需要指定支持的语言版本,可以通过单击“高级”按钮通过项目属性构建选项卡进行设置。在这种情况下,选择 ISO-2 以对应于作为 VS2005 的一部分与 .Net 2.0 一起发布的 C# V2。

如果您需要有关多目标的信息,请参阅:

通过如此配置的项目环境,您将只能使用 .Net 2.0 和 C# 2.0 中提供的功能。这包括您将在对象浏览器中看到的内容。

现在到手头的问题,按值对Dictionary&lt;string, float&gt; 内容进行排序。

一种简单的方法是将键值对提取出来放入一个支持排序的类中。下面的示例使用List&lt;KeyValuePair&lt;string, float&gt;&gt; 来保存值。列表的排序方法被传递一个System.Comparison delegate 到该方法定义比较逻辑。比较逻辑设计为按值(降序)排序,如果值相等,则按键(升序)排序。

public void Test()
{
    Dictionary<string, float> dict = new Dictionary<string, float>();
    dict.Add("A1", 3);
    dict.Add("A2", 30);
    dict.Add("Z", 30);
    dict.Add("A3", 30);
    dict.Add("F", 5);

    List<KeyValuePair<string, float>> sorted = new List<KeyValuePair<string, float>>(dict);
    sorted.Sort(new Comparison<KeyValuePair<string, float>>(CompareKvp));
    foreach(KeyValuePair<string, float> kvp in sorted)
    {
        Console.WriteLine(kvp.ToString());
    }
}

private static Int32 CompareKvp(KeyValuePair<string, float> kvp1, KeyValuePair<string, float> kvp2)
{
    int ret = - kvp1.Value.CompareTo(kvp2.Value); // negate for descending
    if (ret == 0)
    {
        ret = kvp1.Key.CompareTo(kvp2.Key); // Ascend comp for Key
    }
    return ret; 
}

这个例子将产生有序的键值对:

[A2, 30]
[A3, 30]
[Z, 30]
[F, 5]
[A1, 3]

【讨论】:

  • 另一种测试 .net 2 支持的方法 - 获取 Unity unity3d.com/get-unity/download/archive
  • 好的,所以我的愚蠢问题是……字典变成列表了吗?为什么不把它写成字典呢?
  • Dictionary Class 实现了几个接口;其中之一是IEnumerable&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;。 List](docs.microsoft.com/en-us/dotnet/api/… 的 ]constructors 之一接受 IEnumerable 作为列表源。
  • “为什么不把它写成字典呢?” - 字典本身不支持排序,因此您的原始问题。 LINQ 只是一组将 IEnumerable 用作项目源的方法。我选择了List&lt;T&gt;,因为它包含一个 Sort 方法。
  • 嗯,好吧,有没有比创建一个新字典并在最后一个foreach 中显示console.writeline 的位置填充字典更好的方法呢?目标是能够轻松地通过键访问值。
猜你喜欢
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 2016-03-10
  • 1970-01-01
  • 1970-01-01
  • 2015-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多