如何在C#中按两列对矩阵(DataTable)进行分组?
在C#中对DataTable按多列分组的实现方法
针对你需要将DataTable中column1和column2值均相同的行归为一组的需求,以下是两种常用的实现方式:
方法一:使用LINQ to DataSet(推荐)
这种方式代码简洁、可读性高,是处理DataTable分组的首选方案。需要确保项目引用了System.Data.DataSetExtensions程序集,并引入System.Linq命名空间。
代码示例
using System; using System.Data; using System.Linq; class Program { static void Main() { // 示例DataTable(假设已初始化并填充数据) DataTable dt = new DataTable(); dt.Columns.Add("column1", typeof(string)); dt.Columns.Add("column2", typeof(int)); dt.Columns.Add("column3", typeof(decimal)); dt.Rows.Add("A", 1, 100.5m); dt.Rows.Add("A", 1, 200.3m); dt.Rows.Add("B", 2, 150.7m); dt.Rows.Add("A", 2, 300.2m); dt.Rows.Add("B", 2, 400.9m); // 按column1和column2分组,处理DBNull避免异常 var groups = dt.AsEnumerable() .GroupBy(row => new { Column1 = row.IsNull("column1") ? null : row["column1"], Column2 = row.IsNull("column2") ? null : row["column2"] }); // 遍历分组并输出结果 foreach (var group in groups) { Console.WriteLine($"分组键:column1={group.Key.Column1}, column2={group.Key.Column2}"); foreach (DataRow row in group) { Console.WriteLine($" column3值:{row["column3"]}"); } } } }
说明
dt.AsEnumerable()将DataTable转换为支持LINQ操作的DataRow集合- 匿名类型作为分组键,同时处理列值为
DBNull的情况,避免分组逻辑异常 group.Key可获取当前组的column1和column2值,group本身是该组所有DataRow的集合
方法二:手动使用字典分组
如果项目无法使用LINQ,可通过字典手动实现分组逻辑,将(column1, column2)的组合作为字典的键,对应的值为该组的DataRow列表。
代码示例
using System; using System.Data; using System.Collections.Generic; class Program { static void Main() { // 示例DataTable DataTable dt = new DataTable(); dt.Columns.Add("column1", typeof(string)); dt.Columns.Add("column2", typeof(int)); dt.Columns.Add("column3", typeof(decimal)); dt.Rows.Add("A", 1, 100.5m); dt.Rows.Add("A", 1, 200.3m); dt.Rows.Add("B", 2, 150.7m); dt.Rows.Add("A", 2, 300.2m); dt.Rows.Add("B", 2, 400.9m); // 字典存储分组,键为column1和column2的组合 Dictionary<Tuple<object, object>, List<DataRow>> groupsDict = new Dictionary<Tuple<object, object>, List<DataRow>>(); foreach (DataRow row in dt.Rows) { // 获取列值并处理DBNull object val1 = row.IsNull("column1") ? DBNull.Value : row["column1"]; object val2 = row.IsNull("column2") ? DBNull.Value : row["column2"]; var key = Tuple.Create(val1, val2); if (!groupsDict.ContainsKey(key)) { groupsDict[key] = new List<DataRow>(); } groupsDict[key].Add(row); } // 遍历字典输出分组结果 foreach (var kvp in groupsDict) { Console.WriteLine($"分组键:column1={kvp.Key.Item1}, column2={kvp.Key.Item2}"); foreach (DataRow row in kvp.Value) { Console.WriteLine($" column3值:{row["column3"]}"); } } } }
说明
Tuple<object, object>作为字典键,确保column1和column2的组合唯一- 手动遍历每一行,判断键是否存在,不存在则创建新列表,存在则添加当前行
- 同样处理了
DBNull的情况,保证分组逻辑的准确性
注意事项
- 数据类型匹配:确保分组时
column1和column2的值类型一致,避免因类型差异导致分组错误(如字符串"1"和整数1会被视为不同键) - 空值处理:若列可能存在
DBNull值,必须提前处理,否则会引发异常或分组不准确 - 性能考虑:超大DataTable场景下,两种方式性能差异不大,可根据项目环境选择
内容的提问来源于stack exchange,提问作者Balázs Kis
相关产品推荐
相关产品推荐

