如何对DataTables指定列的同值分组按连续数值条件筛选行数据
解决方案
核心逻辑说明
针对需求,按以下步骤处理即可实现筛选:
- 按
Name字段对DataTable所有行分组,每组对应单个用户的全部月度数据 - 对每组内的行,先将
Month字符串转换为DateTime类型,再按时间升序排序,保证最新月份数据排在分组尾部 - 从每组的尾部往前倒序遍历,检查相邻的两条数据是否同时满足
Score >= 5,找到第一组符合要求的连续两个月后,直接将这两条数据加入结果集(无需往前查找更早的记录,保证取到的是最近的符合条件的数据) - 最终将所有符合条件的行整合,就是需要展示的结果
用给出的示例数据验证:
- Allison分组排序后顺序为June 2021(Score=5)、July 2021(Score=7)、August 2021(Score=3),倒序检查首先看August和July:August Score为3不满足要求;再往前看July和June:两者Score都>=5,符合要求,因此保留这两行
- Benjamin分组排序后为June 2021(Score=10)、July 2021(Score=4),倒序检查July和June:July Score为4不满足要求,无符合条件的记录,因此不展示
C# 实现代码
// 原始数据源DataTable,替换为实际的DataTable实例即可 DataTable originalDt = GetYourOriginalDataTable(); // 定义结果DataTable,结构和原始表一致 DataTable resultDt = originalDt.Clone(); // 按Name分组处理 var userGroups = originalDt.AsEnumerable() .GroupBy(row => row.Field<string>("Name")); foreach (var group in userGroups) { // 将分组内的行按月份升序排序 var sortedRows = group.OrderBy(row => DateTime.ParseExact(row.Field<string>("Month"), "MMMM yyyy", System.Globalization.CultureInfo.InvariantCulture)) .ToList(); // 倒序查找最近的连续两个月Score>=5的记录 for (int i = sortedRows.Count - 1; i >= 1; i--) { int scoreCurrent = sortedRows[i].Field<int>("Score"); int scorePrev = sortedRows[i - 1].Field<int>("Score"); if (scoreCurrent >=5 && scorePrev >=5) { // 找到符合条件的两条记录,加入结果 resultDt.ImportRow(sortedRows[i-1]); resultDt.ImportRow(sortedRows[i]); // 只需要最近的,找到就跳出循环 break; } } } // resultDt就是最终筛选后要展示的数据
代码注意事项
- 如果
Score字段是字符串类型,需要先转成int再做比较,避免类型报错 - 如果存在月份格式不标准的情况,可以在
DateTime.ParseExact方法里加容错处理,避免解析报错
内容的提问来源于stack exchange,提问作者Rawan Al Maawali
相关产品推荐
相关产品推荐

