C#使用ContainsAny过滤字符串时如何实现精确匹配排除近似值
问题根因
- 现有
ContainsAny扩展方法仅做子串包含校验,只要EMPNO字段出现M1子串就返回true,因此所有包含M1的记录都会被命中,无法过滤掉同时存在M2、M3等其他M开头编号的记录,不符合你的过滤规则。 - 遍历
Qry1为EmpTagNo赋值时,采用的是顺序覆盖逻辑,最后一条匹配记录的EMPTAG值为40,覆盖了之前的15、20,导致最终输出结果不符合预期。
修复方案
你的EMPNO字段用+作为片段分隔符,调整匹配逻辑为:拆分EMPNO为独立片段后,校验所有格式为M+数字的片段只能有M1一个值,同时满足包含MAP的要求即可。
代码调整示例
方式1:直接修改查询逻辑(无需改扩展方法)
private void button7_Click(object sender, EventArgs e) { List<string> valcontains = new List<string>() { "MAP" }; List<string> Empcontains = new List<string>() { "M1" }; int EmpTagNo = 0; DataTable tblData = new DataTable(); tblData.Columns.Add("EMPNO", typeof(string)); tblData.Columns.Add("EMPTAG", typeof(int)); tblData.Columns.Add("EMPDEP", typeof(string)); tblData.Rows.Add("(MAP) KL+M1+XZ+X1+HM", "15", "CIV"); tblData.Rows.Add("(MAP) KL+M1+M3+X1+HM", "20", "MEC"); tblData.Rows.Add("(MAP) KL+M1+M5+X1+HM+M7", "40", "IT"); tblData.Rows.Add("(MAP) KL+M1+M5+X1+HM+M7", "40", "IT"); tblData.Rows.Add("(MAP) KL+M1+M5+X1+HM+M7", "40", "IT"); tblData.Rows.Add("(MAP) KL+M1+M5+X1+HM+M7", "40", "IT"); tblData.Rows.Add("(MAP) KL+M1+M5+X1+HM+M7", "40", "CIV"); // 过滤符合要求的记录 var matchedRecords = tblData.AsEnumerable() .Where(r => // 校验包含MAP valcontains.Any(r.Field<string>("EMPNO").Contains) && // 拆分EMPNO片段,校验M开头数字格式的片段只有M1 r.Field<string>("EMPNO").Split('+') .Where(seg => System.Text.RegularExpressions.Regex.IsMatch(seg, @"^M\d+$")) .All(seg => Empcontains.Contains(seg)) ).ToList(); if (matchedRecords.Any()) { // 直接取第一条匹配记录的EMPTAG,避免覆盖 EmpTagNo = matchedRecords.First().Field<int>("EMPTAG"); } }
方式2:新增扩展方法适配通用场景
如果需要复用该匹配逻辑,可以在ContainsStringExtensions类中新增方法:
public static class ContainsStringExtensions { public static bool ContainsAny(this string haystack, IEnumerable<string> filterList) { return haystack != null && filterList.Any(haystack.Contains); } // 新增精确匹配分隔片段的方法 public static bool MatchExactMSegment(this string haystack, IEnumerable<string> allowedMSegs, char separator = '+') { if (string.IsNullOrEmpty(haystack) || allowedMSegs == null || !allowedMSegs.Any()) return false; var segments = haystack.Split(separator); // 筛选所有M开头+数字的片段 var mSegments = segments.Where(seg => System.Text.RegularExpressions.Regex.IsMatch(seg, @"^M\d+$")); // 要求所有M类片段都在允许列表内 return mSegments.All(seg => allowedMSegs.Contains(seg)); } }
调用时直接替换where条件即可:
var matchedRecords = tblData.AsEnumerable() .Where(r => r.Field<string>("EMPNO").ContainsAny(valcontains) && r.Field<string>("EMPNO").MatchExactMSegment(Empcontains) ).ToList();
修改后只会命中第一条符合要求的记录,EmpTagNo最终值为预期的15。
内容的提问来源于stack exchange,提问作者Gani_tpt
相关产品推荐
相关产品推荐

