C# DataTable删除间隔60秒内同ID同账单编码重复记录方案咨询
C# DataTable按时间间隔去重实现方案
核心逻辑
- 按相同的
IdNumber和BillingCode对记录分组 - 每组内按
EntryDate升序排序,保证最早的记录在前 - 遍历每组内的排序后记录,仅保留与上一条保留记录的时间间隔>60秒的记录
完整Linq实现
引用命名空间
using System; using System.Collections.Generic; using System.Data; using System.Linq;
核心处理代码
// 假设源DataTable名为sourceDt var filteredRows = sourceDt.AsEnumerable() // 按IdNumber和BillingCode分组 .GroupBy(row => new { IdNumber = row.Field<string>("IdNumber"), BillingCode = row.Field<int>("BillingCode") }) .SelectMany(group => { // 每组内按EntryDate升序排序 var sortedGroup = group.OrderBy(row => row.Field<DateTime>("EntryDate")).ToList(); var keepRows = new List<DataRow>(); DateTime? lastKeepTime = null; foreach(var row in sortedGroup) { var currentTime = row.Field<DateTime>("EntryDate"); // 第一条直接保留,和上一条保留记录间隔超过60秒也保留 if(!lastKeepTime.HasValue || (currentTime - lastKeepTime.Value).TotalSeconds > 60) { keepRows.Add(row); lastKeepTime = currentTime; } } return keepRows; }) .ToList(); // 生成新的去重后DataTable DataTable resultDt = filteredRows.Any() ? filteredRows.CopyToDataTable() : sourceDt.Clone();
原表直接删除多余行的实现
如果不需要保留原数据,可以直接在原DataTable上操作:
// 计算要删除的行 var deleteRows = sourceDt.AsEnumerable().Except(filteredRows).ToList(); foreach(var row in deleteRows) { sourceDt.Rows.Remove(row); } sourceDt.AcceptChanges();
说明
DataTable原生的Select方法仅支持简单条件过滤,无法处理这种依赖前后行关系的滑动窗口判断,结合Linq是当前最高效的实现方式,测试完全匹配你给出的样例输入输出要求。
内容的提问来源于stack exchange,提问作者johan
相关产品推荐
相关产品推荐

