如何按含年月字符串格式的键对Dictionary进行排序?
按时间顺序排序Dictionary的问题解决方法
问题场景
有一个存储年月字符串为Key、整数为Value的Dictionary,需要按实际时间先后顺序排序,但使用默认的SortedDictionary得到的是字典序结果,不符合预期。
原Dictionary定义代码:
Dictionary<string, int> map = new Dictionary<string, int>(); map["Sep 20"] = 10; map["Oct 20"] = 11; map["Nov 20"] = 23; map["Jan 21"] = 15; map["Feb 20"] = 50; map["Mar 20"] = 23;
尝试的排序代码:
SortedDictionary<string, int> sortMap = new SortedDictionary<string, int>(map); foreach (var entry in sortMap) { Console.WriteLine(entry.Key + "\t" + entry.Value); }
期望输出
Feb 20 50 Mar 20 23 Sep 20 10 Oct 20 11 Nov 20 23 Jan 21 15
实际输出
Feb 20 50 Jan 21 15 Mar 20 23 Nov 20 23 Oct 20 11 Sep 20 10
问题原因
SortedDictionary默认使用字符串字典序排序,而非时间顺序。比如"Jan 21"的首字母J在M之前,所以排在"Mar 20"前面,但实际时间上2020年的所有月份都早于2021年1月,因此默认排序逻辑不满足需求。
解决方案
要实现按时间顺序排序,需要将Key字符串解析为时间对象后比较,以下是两种常用实现方式:
方法1:自定义比较器的SortedDictionary
创建一个实现IComparer<string>的比较器,将年月字符串转换为DateTime后比较时间先后:
using System.Globalization; public class MonthYearComparer : IComparer<string> { public int Compare(string x, string y) { // 按"MMM yy"格式解析字符串为DateTime(英文月份缩写+两位年份) if (DateTime.TryParseExact(x, "MMM yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateX) && DateTime.TryParseExact(y, "MMM yy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime dateY)) { return dateX.CompareTo(dateY); } // 解析失败时回退到字典序 return string.Compare(x, y); } }
使用该比较器初始化SortedDictionary并添加元素:
SortedDictionary<string, int> sortMap = new SortedDictionary<string, int>(new MonthYearComparer()); foreach (var entry in map) { sortMap.Add(entry.Key, entry.Value); } // 遍历输出 foreach (var entry in sortMap) { Console.WriteLine($"{entry.Key}\t{entry.Value}"); }
方法2:Linq直接排序生成集合
如果不需要长期维护有序集合,可直接用Linq对原Dictionary的元素排序,生成新的有序集合:
using System.Linq; using System.Globalization; var sortedEntries = map.OrderBy(entry => DateTime.ParseExact(entry.Key, "MMM yy", CultureInfo.InvariantCulture)); foreach (var entry in sortedEntries) { Console.WriteLine($"{entry.Key}\t{entry.Value}"); }
注意事项
- 确保年月字符串格式统一,若你的格式不是
"MMM yy",需调整ParseExact中的格式字符串。 - 使用
CultureInfo.InvariantCulture可避免因系统区域设置不同导致的月份解析失败(比如非英文系统的月份缩写差异)。
内容的提问来源于stack exchange,提问作者Sawan Meshram
相关产品推荐
相关产品推荐

