如何按键对字典进行排序

60

我有一个字典Dictionary<string, Point>

键是c1,c3,c2,t1,,t4,t2,我希望将它们排序为c1,c2,c3,t1,t2,t3

我正在尝试使用

Input.OrderBy(key => key.Key );

但它并不起作用。

有什么办法可以解决这个问题吗?


1
它是根本没有排序,还是只是不按你期望的顺序排序? - Beth Lang
1
参考此链接,其中有一些非常好的示例。 - COLD TOLD
好的,我在下面的答案中提供的内容应该对您有效。 - Beth Lang
2
对 C# 字典进行排序 - kyrylomyr
8个回答

53

Input.OrderBy并不对字典进行排序,它创建的是一个按照特定顺序返回项目的查询。

或许可以使用OrderedDictionary来满足您的需求。

或者使用泛型SortedDictionary


29

由于 Input.OrderBy 创建了一个按顺序返回项的查询,所以只需将其分配给同一个字典即可。

objectDict = objectDict.OrderBy(obj => obj.Key).ToDictionary(obj => obj.Key, obj => obj.Value);


28

像这样将未排序的对象加载到 SortedDictionary 对象中:

var sortedCustomerData 
    = new SortedDictionary<string, string>(unsortedCustomerData);

其中unsortedCustomerData是相同泛型类型(Dictionary string, string或在您的情况下为string, point)。它会自动按键排序新对象。

根据 MSDN:SortedDictionary<TKey, TValue>(IDictionary<TKey, TValue>): 初始化一个 SortedDictionary<TKey, TValue> 类的新实例,该实例包含从指定的 IDictionary<TKey, TValue> 中复制的元素,并且对于键类型使用默认的 IComparer<T> 实现。


8

我猜你可能认为它将对输入进行排序。实际上,OrderBy方法返回一个有序的IOrderedEnumerable实例,其中包含相同的值。如果你想保留返回值,可以按照以下方式操作:

IOrderedEnumerable orderedInput
orderedInput = Input.OrderBy(key=>key.Key)

大多数修改集合的方法都遵循这种模式。它这样做是为了不改变原始的集合实例。这可以保护你在不打算更改实例时免受意外更改的影响。如果你只想使用排序后的实例,那么只需像上面所示一样将变量设置为方法返回即可。

4
以下代码使用两个更多的listsort一个字典。
using System;
using System.Collections.Generic;
using System.Drawing;

namespace ConsoleApplication1 {
    class Program {
        static void Main(string[] args) {
            Dictionary<string,Point> r=new Dictionary<string,Point>();
            r.Add("c3",new Point(0,1));
            r.Add("c1",new Point(1,2));
            r.Add("t3",new Point(2,3));
            r.Add("c4",new Point(3,4));
            r.Add("c2",new Point(4,5));
            r.Add("t1",new Point(5,6));
            r.Add("t2",new Point(6,7));
            // Create a list of keys
            List<string> zlk=new List<string>(r.Keys);
            // and then sort it.
            zlk.Sort();
            List<Point> zlv=new List<Point>();
            // Readd with the order.
            foreach(var item in zlk) {
                zlv.Add(r[item]);
            }
            r.Clear();
            for(int i=0;i<zlk.Count;i++) {
                r[zlk[i]]=zlv[i];
            }
            // test output
            foreach(var item in r.Keys) {
                Console.WriteLine(item+" "+r[item].X+" "+r[item].Y);
            }
            Console.ReadKey(true);
        }
    }
}

上面代码的输出如下所示。
c1 1 2
c2 4 5
c3 0 1
c4 3 4
t1 5 6
t2 6 7
t3 2 3

0

这取决于您的需求。如果您需要将键作为列表输出,一次排序即可解决问题。我已经编写了下面的测试代码,您可以运行并查看如何实现按键排序。

[Fact]
public void SortDict()
{
    // Arrange
    var initial = new Dictionary<string, bool>()
    {
        {"c1", true },
        {"c3", true },
        {"c2", true },
        {"t1", true },
        {"t3", true },
        {"t2", true },
    };
    var expected = new List<string>() { "c1", "c2", "c3", "t1", "t2", "t3" };

    // Act
    var actual = initial.OrderBy(k => k.Key).Select(k => k.Key)
        .ToList();

    // Assert
    actual.ShouldBeEquivalentTo(expected);
}

如果您需要始终按顺序排序键,则应使用SortedDictionary。在下面的示例中,我正在使用其构造函数创建一个SortedDictionary,并将旧字典作为参数传递。您可以运行测试并验证结果。

[Fact]
public void SortDictUsingLinq()
{
    // Arrange
    var initial = new Dictionary<string, bool>()
    {
        {"c1", true },
        {"c3", true },
        {"c2", true },
        {"t1", true },
        {"t3", true },
        {"t2", true },
    };
    var expected = new List<string>() { "c1", "c2", "c3", "t1", "t2", "t3" };

    // Act
    var sortedDict = new SortedDictionary<string, bool>(initial);

    // Assert
    sortedDict.Keys.ToList().ShouldBeEquivalentTo(expected);
}

SortedDictionary相比于Dictionary具有更快的O(log n)插入和检索时间,而Dictionary则具有O(1)。因此,如果您只需要对元素进行一次或很少排序,并且经常插入和删除,则一次排序就是您所需的。


0

我使用了

var l =  Input.OrderBy(key => key.Key);

然后我将其转换为字典


3
我说过:这不是对字典进行排序!它只是创建了一个已排序的“视图”。 - Emond

-6

好的,检查一下,应该可以工作。

var r = new Dictionary<string, Point>();
r.Add("c3", new Point(0, 0));
r.Add("c1", new Point(0, 0));
r.Add("t3", new Point(0, 0));
r.Add("c4", new Point(0, 0));
r.Add("c2", new Point(0, 0));
r.Add("t1", new Point(0, 0));
r.Add("t2", new Point(0, 0));
var l = r.OrderBy(key => key.Key);
var dic = l.ToDictionary((keyItem) => keyItem.Key, (valueItem) => valueItem.Value);

foreach (var item in dic)
{

    Console.WriteLine(item.Key);
}
Console.ReadLine();

2
-1:这样做不行。你只是创建了另一个没有排序的字典。它可能适用于小型字典,但最终会失败。 - leppie
我们在聊天中交流过,我知道他想要什么,所以我帮助他解决了他的问题。 - DeveloperX
14
我猜人们之所以给它负评是因为它没有回答问题。由于我们无法看到聊天记录,所以人们可能不认为它是对我们看到的问题有用的答案。 - Emond
正如 @leppie 所提到的,这种方法最终会失败,使用 SortedDictionary 是正确的做法。 - Thomas Mondel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接