如何按键对字典进行排序

本文关键字:排序 字典 何按键 | 更新日期: 2023-09-27 18:14:16

我有字典Dictionary<string, Point>

键是c1,c3,c2,t1, t4,t2我想把它们排序成c1,c2,c3,t1,t2,t3

我正在尝试使用

进行排序
Input.OrderBy(key => key.Key );

但是它不起作用

知道怎么解决这个问题吗

如何按键对字典进行排序

Input.OrderBy不对字典进行排序,它创建一个查询,以特定的顺序返回条目。

也许OrderedDictionary给了你想要的。

或者使用Generic SortedDictionary

将未排序的对象加载到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>实现作为密钥类型

自输入。OrderBy创建一个查询,该查询以有序的顺序返回条目,只需将其分配给相同的字典。

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

只是一个猜测,但它看起来像你假设它要排序输入。OrderBy方法实际上返回包含相同值的IOrderedEnumerable的有序实例。如果您想保留返回值,可以执行以下操作:

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

大多数修改集合的方法都遵循相同的模式。它这样做是为了不更改原始集合实例。这可以防止您在不打算更改实例时意外更改实例。如果您想只使用排序实例,那么只需将变量设置为方法的返回值,如上面所示。

下面的代码使用另外两个列表对字典进行排序。

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

我用

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

并将其转换为Dictionary

这取决于你的需要。如果您需要以列表的形式输出键,那么一次性排序就可以了。我做了下面的测试,你可以运行,看看如何实现按键排序。

[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);
}
0 (1)Dictionary相比,

SortedDictionary的插入和检索次数 0 (log n)。因此,如果只有一次或很少需要对元素进行排序,并且您经常插入和删除一次,那么排序将是您所需要的。

ok,检查一下,应该可以工作了

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