C#如何实现按Person.Name排序的字典存储人员及其订单数据
C# 实现按姓名排序的人员订单存储方案
核心解决思路
你的需求可通过两种方案实现,均满足「一次排序、永久使用」的要求,无需每次展示前重新排序:
方案一:自定义排序键的 SortedDictionary 实现
适合同时需要按姓名排序遍历和按键快速查找的场景,通过自定义比较规则控制排序逻辑:
- 自定义包含姓名、ID的键结构,实现
IComparable<T>接口,优先按姓名排序,姓名相同则按ID排序保证键唯一 - 直接使用
SortedDictionary存储,插入时自动完成排序,后续遍历顺序固定
代码实现
// 自定义人员排序键,内置排序规则 public struct PersonSortKey : IComparable<PersonSortKey> { public string Name { get; } public string Id { get; } public PersonSortKey(string name, string id) { Name = name; Id = id; } public int CompareTo(PersonSortKey other) { // 优先按姓名升序 int nameCompare = string.Compare(Name, other.Name, StringComparison.Ordinal); if (nameCompare != 0) return nameCompare; // 姓名相同按ID排序,保证键全局唯一 return string.Compare(Id, other.Id, StringComparison.Ordinal); } } // 初始化字典 var lastOrders = new SortedDictionary<PersonSortKey, Queue<Order>>(); // 插入示例 lastOrders.Add(new PersonSortKey("Anne", "n4"), new Queue<Order>(new[] { new Order("Salami"), new Order("Ananas") })); lastOrders.Add(new PersonSortKey("Ben", "n2"), new Queue<Order>(new[] { new Order("Apple") })); lastOrders.Add(new PersonSortKey("Ben", "n3"), new Queue<Order>(new[] { new Order("Banana") })); lastOrders.Add(new PersonSortKey("Cesar", "n1"), new Queue<Order>(new[] { new Order("Banana"), new Order("Cheese") }));
遍历直接foreach即可输出你需要的顺序。
方案二:双索引预排序实现(更适合你的场景)
你的场景中人员数据静态,该方案性能更优:
- 用普通
Dictionary按ID存储订单队列,保证更新订单时O(1)查找效率 - 初始化时一次性生成按姓名升序的展示列表,列表中存储队列的引用,后续订单更新会自动同步到列表中,无需重新排序
代码实现
// 按ID索引的订单字典,用于快速更新订单 private readonly Dictionary<string, Queue<Order>> _orderById = new Dictionary<string, Queue<Order>>(); // 预排序的展示列表,初始化后固定顺序 private List<(string PersonName, Queue<Order> Orders)> _sortedDisplayList; // 应用启动时调用一次初始化即可 public void InitStaticData(IEnumerable<Person> allPersons) { // 初始化ID索引 foreach (var person in allPersons) { _orderById.Add(person.Id, new Queue<Order>()); } // 一次性完成排序,后续无需修改 _sortedDisplayList = allPersons .OrderBy(p => p.Name) .Select(p => (p.Name, _orderById[p.Id])) .ToList(); } // 更新订单方法,O(1)效率 public void AddNewOrder(string personId, Order order) { if (_orderById.TryGetValue(personId, out var queue)) { queue.Enqueue(order); } } // 展示时直接遍历预排序列表 public void PrintAllOrders() { foreach (var item in _sortedDisplayList) { var orderNames = string.Join(", ", item.Orders.Select(o => o.Name)); Console.WriteLine($"- {item.PersonName}: {orderNames}"); } }
之前方案问题说明
你之前使用KeyValuePair作为复合键时排序不符合预期,是因为KeyValuePair的默认比较逻辑优先比较第一个字段,你把ID放在了第一位,所以会按ID排序,调整字段顺序后配合自定义比较器也可以实现需求,但自定义结构体的可读性更强。
内容的提问来源于stack exchange,提问作者Louise Delgado
相关产品推荐
相关产品推荐

