C#新手如何优化多条件判定DataTable重复记录并更新Remark的操作
问题核心原因
你当前代码执行慢的核心问题是嵌套循环的时间复杂度过高:先单独查询每个条件的重复键集合,再逐行遍历所有行去匹配所有重复键,相当于17000行 × 每个条件的重复组数量,匹配操作完全是多余的。
最优优化方案
不需要单独查重复键再匹配,分组时直接拿到对应重复组的所有行,直接更新Remark即可,每个条件仅需遍历一次全表,4个条件总共遍历4次17000行,执行速度可以达到毫秒级。
实现代码如下:
// 处理条件1:Name + MemberNoA 重复超过2次 var duplicateGroups1 = dt.AsEnumerable() .GroupBy(row => new { Name = row.Field<string>("Name") ?? string.Empty, MemberNoA = row.Field<string>("MemberNoA") ?? string.Empty }) .Where(group => group.Count() > 2); foreach (var group in duplicateGroups1) { foreach (var row in group) { row["Remark"] = $"{row["Remark"]}Criteria 1 match\r\n"; } } // 处理条件2:Name + MemberNoB 重复超过2次 var duplicateGroups2 = dt.AsEnumerable() .GroupBy(row => new { Name = row.Field<string>("Name") ?? string.Empty, MemberNoB = row.Field<string>("MemberNoB") ?? string.Empty }) .Where(group => group.Count() > 2); foreach (var group in duplicateGroups2) { foreach (var row in group) { row["Remark"] = $"{row["Remark"]}Criteria 2 match\r\n"; } } // 处理条件3:Name + DriverLicense 重复超过2次 var duplicateGroups3 = dt.AsEnumerable() .GroupBy(row => new { Name = row.Field<string>("Name") ?? string.Empty, DriverLicense = row.Field<string>("DriverLicense") ?? string.Empty }) .Where(group => group.Count() > 2); foreach (var group in duplicateGroups3) { foreach (var row in group) { row["Remark"] = $"{row["Remark"]}Criteria 3 match\r\n"; } } // 处理条件4:Name + MobileNo 重复超过2次 var duplicateGroups4 = dt.AsEnumerable() .GroupBy(row => new { Name = row.Field<string>("Name") ?? string.Empty, MobileNo = row.Field<string>("MobileNo") ?? string.Empty }) .Where(group => group.Count() > 2); foreach (var group in duplicateGroups4) { foreach (var row in group) { row["Remark"] = $"{row["Remark"]}Criteria 4 match\r\n"; } }
简化版写法
如果你不想写重复代码,可以把重复逻辑封装成通用方法,代码更简洁:
// 定义通用重复处理方法 void ProcessDuplicateGroup<TKey>(Func<DataRow, TKey> keyGenerator, string remarkContent) { var duplicateGroups = dt.AsEnumerable() .GroupBy(keyGenerator) .Where(g => g.Count() > 2); foreach (var group in duplicateGroups) { foreach (var row in group) { row["Remark"] = $"{row["Remark"]}{remarkContent}\r\n"; } } } // 一次性调用处理4个条件 ProcessDuplicateGroup(r => new { N = r.Field<string>("Name") ?? "", A = r.Field<string>("MemberNoA") ?? "" }, "Criteria 1 match"); ProcessDuplicateGroup(r => new { N = r.Field<string>("Name") ?? "", B = r.Field<string>("MemberNoB") ?? "" }, "Criteria 2 match"); ProcessDuplicateGroup(r => new { N = r.Field<string>("Name") ?? "", L = r.Field<string>("DriverLicense") ?? "" }, "Criteria 3 match"); ProcessDuplicateGroup(r => new { N = r.Field<string>("Name") ?? "", M = r.Field<string>("MobileNo") ?? "" }, "Criteria 4 match");
额外优化说明
代码中加了?? string.Empty处理字段为空的情况,避免空值导致分组逻辑异常,你可以根据实际业务需求决定是否保留。
内容的提问来源于stack exchange,提问作者Chi-fung LAM
相关产品推荐
相关产品推荐

