C# 使用LINQ按属性分组按指定列表排序每组取首项报错如何解决
异常原因
- 抛出
At least one object must implement IComparable的核心原因是你调用了针对自定义类的Min()方法:Min()需要比较集合中元素的大小,而你的ExampleDataClass没有实现IComparable<ExampleDataClass>接口,LINQ无法判断两个自定义对象的大小关系。 - 额外的逻辑冗余:你已经通过
OrderBy按照国家优先级给分组内的数据排好序了,完全不需要调用Min(),直接取排序后的第一条数据即可。
修正后的代码
把核心查询逻辑和输出部分修改即可,完整可运行代码如下:
using System; using System.Collections.Generic; using System.Linq; public class Program { public static void Main() { var countryOrder = new List<string> { "UK", "KE", "AU", "USA"}; var data = new List<ExampleDataClass> { new ExampleDataClass { Name = "Alice", Country = "UK", Age = 30 }, new ExampleDataClass { Name = "Bob", Country = "KE", Age = 20 }, new ExampleDataClass { Name = "Charlie", Country = "UK", Age = 30 }, new ExampleDataClass { Name = "Alice", Country = "KE", Age = 40 }, new ExampleDataClass { Name = "Bob", Country = "AU", Age = 50 }, new ExampleDataClass { Name = "David", Country = "USA", Age = 25 } }; var reducedData = data .GroupBy(x => x.Name) // 排序后直接取第一条,不需要调用Min() .Select(g => g.OrderBy(item => countryOrder.IndexOf(item.Country)).First()) .ToList(); // 修正输出逻辑,原代码错误输出整个集合 reducedData.ForEach(item => Console.WriteLine($"name: {item.Name}, country: {item.Country}, age: {item.Age}")); } } class ExampleDataClass { public string Name { get; set; } public string Country { get; set; } public int Age { get; set; } }
可选优化
如果存在数据里的国家不在预设countryOrder列表的情况,IndexOf会返回-1,导致这类数据排在最前面。如果需要把不在优先级列表里的国家排在最后,可以修改排序规则:
.OrderBy(item => { var index = countryOrder.IndexOf(item.Country); return index < 0 ? int.MaxValue : index; })
内容的提问来源于stack exchange,提问作者k.wahome
相关产品推荐
相关产品推荐

