如何使用LINQ对DataTable分组排序去重并解决匿名类型声明异常
错误原因
你的代码存在两个明确的语法错误,以及一个潜在的业务逻辑问题:
- group by 子句的匿名类型未显式声明属性名,C# 无法从
Field<T>方法调用自动推导匿名类属性名,必须手动指定。 - 分组后的组内集合变量名是
g,你子查询中使用的groupedItems属于未定义变量,直接遍历g即可获取组内所有行。 - 潜在问题:当前Col3存储的是字符串格式的数字,直接按字符串排序会出现
"10" < "2"的不符合预期的结果,建议转成数值类型排序。
修复后的代码
查询语法写法
var result = from record in datatable.AsEnumerable() group record by new { Col1 = record.Field<string>("Col1"), Col2 = record.Field<string>("Col2") } into g // 组内按Col3数值降序,取第一条 let targetRow = g.OrderByDescending(row => int.Parse(row.Field<string>("Col3"))).First() select targetRow; // 若需要转回DataTable直接调用CopyToDataTable即可 // DataTable resultTable = result.CopyToDataTable();
流式写法
var result = datatable.AsEnumerable() .GroupBy(row => new { Col1 = row.Field<string>("Col1"), Col2 = row.Field<string>("Col2") }) .Select(g => g.OrderByDescending(row => int.Parse(row.Field<string>("Col3"))).First());
优化建议
如果Col3本身就是数值类型,建议在初始化DataTable时就指定列类型,避免后续频繁类型转换:
// 初始化时指定Col3为int类型 datatable.Columns.Add("Col3", typeof(int)); // 赋值时直接传入数值 row1.ItemArray = new object[] { "A", "B", 1 };
修改后排序时不需要再做字符串转int的操作,直接写row.Field<int>("Col3")即可。
自定义规则扩展
你可以任意修改组内选行的逻辑满足不同业务需求:
- 保留Col3最小的行:将
OrderByDescending改为OrderBy - 保留符合特定条件的行:将排序逻辑替换为
Where条件,比如g.First(row => row.Field<string>("Col3") == "1")
内容的提问来源于stack exchange,提问作者Muflix
相关产品推荐
相关产品推荐

