C# 如何用LINQ在同一DataTable新增列展示分组求和结果
LINQ实现分组求和列赋值方案
你当前使用双层嵌套循环的实现存在两个核心问题:一是时间复杂度为平方级,数据量大时匹配效率极低;二是需要额外维护一个存储分组结果的中间DataTable,存在冗余开销。用LINQ可以把整体逻辑优化为线性时间复杂度的实现,完全不需要嵌套循环,具体写法如下:
实现步骤
- 直接基于原DataTable的数据,按
sno字段分组计算求和值,转换为字典结构做快速匹配(字典的查找操作是O(1)时间复杂度,远快于逐行遍历比对) - 确认原表存在
total列,不存在则动态新增 - 逐行遍历原表,从字典中直接读取对应
sno的求和值完成赋值
核心实现代码
// 1. 基于原表直接生成分组求和的字典,无需创建中间结果DataTable var snoTotalMap = table.AsEnumerable() // 按sno字段分组,对空值做兜底处理避免报错 .GroupBy(row => row["sno"]?.ToString() ?? string.Empty) .Select(group => new { SnoKey = group.Key, // 计算当前组的求和值,对列空值做兼容处理 GroupTotal = group.Sum(row => row["需要累加的数值列名"] == DBNull.Value ? 0m : Convert.ToDecimal(row["需要累加的数值列名"])) }) .ToDictionary(res => res.SnoKey, res => res.GroupTotal); // 2. 为原表补全total列 if (!table.Columns.Contains("total")) { table.Columns.Add("total", typeof(decimal)); } // 3. 逐行完成赋值 foreach (DataRow dataRow in table.Rows) { var currentSno = dataRow["sno"]?.ToString() ?? string.Empty; // 从字典中快速取值匹配 if (snoTotalMap.TryGetValue(currentSno, out var total)) { dataRow["total"] = total; } }
可选写法:LINQ关联匹配
如果不习惯手动遍历字典,也可以直接用LINQ的Join语法完成关联匹配,逻辑和上面完全一致:
if (!table.Columns.Contains("total")) { table.Columns.Add("total", typeof(decimal)); } var matchQuery = from sourceRow in table.AsEnumerable() join sumItem in snoTotalMap on sourceRow["sno"]?.ToString() ?? string.Empty equals sumItem.Key select new { Row = sourceRow, SumValue = sumItem.Value }; foreach (var item in matchQuery) { item.Row["total"] = item.SumValue; }
优化效果对比
- 原嵌套循环写法:时间复杂度为
原表行数 * 分组结果行数,当原表有1000行、分组结果有200组时,需要执行20万次比对 - LINQ字典实现:时间复杂度为
原表行数 + 分组结果行数,同样数据规模下仅需要1200次操作,数据量越大效率优势越明显 - 省去了单独创建、维护中间分组结果DataTable的开销
注意:代码中的
需要累加的数值列名需要替换为你实际要做求和统计的列名,避免硬编码列名导致的运行报错。
内容的提问来源于stack exchange,提问作者Bin
相关产品推荐
相关产品推荐

