C#中如何比较含多种格式代码的字符串?求最优实现方案
最优自定义字符串比较实现方案
针对你的需求,标准化代码格式+标记式预期字符串是最符合「高效、易用、易理解」的最优方案,核心思路是:不管代码的显示形式如何,先把任意格式的代码转换成统一的标准格式,再结合标记解析完成整体字符串的匹配,完全不需要因为UI修改代码显示方式而改动测试逻辑。
具体实现步骤
1. 编写代码标准化函数
先实现一个NormalizeCode函数,负责把任何格式的代码转换成统一的标准格式(比如大写无分隔符的XXYYYYYYYY,其中XX是两位字母数字,YYYYYYYY是8位十六进制):
private static string NormalizeCode(string code) { // 移除所有非字母数字的字符,转大写 var cleanedChars = code.Where(char.IsLetterOrDigit).ToArray(); var cleaned = new string(cleanedChars).ToUpperInvariant(); // 验证代码的核心格式合法性 if (cleaned.Length != 10 || !cleaned.Take(2).All(char.IsLetterOrDigit) || !cleaned.Skip(2).All(c => char.IsDigit(c) || (c >= 'A' && c <= 'F'))) { throw new ArgumentException("输入的内容不符合代码格式要求"); } return cleaned; }
这个函数会处理所有你提到的显示形式:
XY 1A2B 3C4E→XY1A2B3C4EXY1A2B3C4E→XY1A2B3C4EXY-1A2B-3C4E→XY1A2B3C4Exy 1a2b 3c4e→XY1A2B3C4E
2. 实现带代码容错的字符串匹配函数
再写一个MatchWithCodeTolerance函数,解析你用{{}}标记的预期字符串,拆分出固定文本和需要容错的代码部分,分别进行匹配:
private static bool MatchWithCodeTolerance(string expectedPattern, string actual) { // 用正则拆分预期字符串,分离固定文本和{{}}包裹的代码 var parts = Regex.Split(expectedPattern, @"{{(.*?)}}"); // 检查标记是否成对 if (parts.Length % 2 == 0) { throw new ArgumentException("预期字符串中的{{}}标记未成对"); } int currentPosition = 0; for (int i = 0; i < parts.Length; i++) { if (i % 2 == 0) { // 处理固定文本部分:直接匹配 var fixedText = parts[i]; if (!actual.Substring(currentPosition).StartsWith(fixedText)) { return false; } currentPosition += fixedText.Length; } else { // 处理代码部分:提取实际字符串中的对应片段,标准化后对比 var expectedRawCode = parts[i]; var expectedStandard = NormalizeCode(expectedRawCode); // 找到下一段固定文本的位置(如果存在) string nextFixedText = i < parts.Length - 1 ? parts[i + 1] : null; string actualCodeSegment; if (nextFixedText != null) { int nextTextIndex = actual.IndexOf(nextFixedText, currentPosition); if (nextTextIndex == -1) { return false; } actualCodeSegment = actual.Substring(currentPosition, nextTextIndex - currentPosition); currentPosition = nextTextIndex; } else { // 代码在字符串末尾 actualCodeSegment = actual.Substring(currentPosition); currentPosition = actual.Length; } // 标准化实际代码并对比 var actualStandard = NormalizeCode(actualCodeSegment); if (actualStandard != expectedStandard) { return false; } } } // 确保实际字符串完全匹配完毕 return currentPosition == actual.Length; }
3. 测试代码的使用
现在你可以按照预期的方式编写测试,只需要把需要容错的代码用{{}}包裹即可:
var actual = GetTheActualValue(); var expected = @"This is a code {{SZ 0467 4FA1}} in a middle of a sentence"; var areEquals = MatchWithCodeTolerance(expected, actual);
其他可选思路
正则表达式匹配方案
如果你更喜欢用正则,可以把预期字符串中的{{XX 0123 4567}}替换成匹配任意代码格式的正则片段,同时验证匹配到的内容标准化后和预期一致。比如:
var expectedCode = "SZ 0467 4FA1"; var expectedStandard = NormalizeCode(expectedCode); // 构建匹配任意代码格式的正则 var regexPattern = Regex.Escape(@"This is a code ") + @"(?<code>[A-Z0-9]{2}[- ]?[A-F0-9]{4}[- ]?[A-F0-9]{4})" + Regex.Escape(@" in a middle of a sentence"); var match = Regex.Match(actual, regexPattern, RegexOptions.IgnoreCase); var areEquals = match.Success && NormalizeCode(match.Groups["code"].Value) == expectedStandard;
这种方案灵活性高,但对于复杂文本的维护成本更高,不如标记式方案直观。
方案对比
| 方案 | 效率 | 易用性 | 可维护性 | 适用场景 |
|---|---|---|---|---|
| 标准化+标记解析 | 高 | 高 | 高 | 测试场景、文本结构固定 |
| 正则表达式匹配 | 中 | 中 | 中 | 复杂文本、动态匹配 |
显然,标准化+标记解析是你的需求的最优选择:它逻辑清晰,测试代码编写简单,后续UI修改代码显示格式时,只需要确保NormalizeCode能处理新格式即可,测试代码完全不需要改动。
内容的提问来源于stack exchange,提问作者user2563824
相关产品推荐
相关产品推荐

