C#中如何高效获取字符串内非X字符的位置并实现跨串位置比对
原实现的核心问题
- 逻辑存在硬伤:遍历到非X字符时调用
stringValue.IndexOf(character),只会返回该字符第一次出现的全局索引,根本拿不到当前遍历位置的真实下标。比如示例字符串末尾的0,也会返回第一个0的位置,最终收集到的索引完全不准。 - 效率拉胯的根源:每匹配到一个非X字符,就触发一次覆盖全字符串的
IndexOf扫描,原本O(n)的遍历直接被拖成O(n²),字符串长度越长性能衰减越明显。另外原代码里用character != "X"做判断,是把char类型和string类型做比较,会触发额外的类型转换开销。
优化方案
核心思路完全不需要冗余的IndexOf调用:遍历字符串时同步维护当前的位置下标,匹配到非X字符时直接把当前下标存入列表,整体时间复杂度可以稳定在O(n)。
基础正确实现
List<int> GetNonXPositions(string stringValue) { // 提前预分配列表容量,避免动态扩容的内存拷贝开销 List<int> charPositions = new List<int>(capacity: stringValue.Length / 2); for (int i = 0; i < stringValue.Length; i++) { // 直接对比char类型的X常量,无类型转换开销 if (stringValue[i] != 'X') { charPositions.Add(i); } } return charPositions; }
极致性能适配(.NET Core 2.1+ / .NET 5+)
如果追求更快的遍历速度,可以用Span<char> 做连续内存访问,相比普通字符串索引访问可以跳过不必要的边界检查,遍历速度能再提30%~50%:
List<int> GetNonXPositionsFast(string stringValue) { List<int> charPositions = new List<int>(stringValue.Length / 2); ReadOnlySpan<char> valueSpan = stringValue.AsSpan(); for (int i = 0; i < valueSpan.Length; i++) { if (valueSpan[i] != 'X') { charPositions.Add(i); } } return charPositions; }
跨字符串匹配逻辑扩展
拿到非X字符的索引列表后,要比对另一字符串的对应位置内容完全没有额外性能损耗,直接遍历索引取位对比即可:
bool CompareByPositions(string source, string target, List<int> positions) { // 先做长度边界校验,避免越界异常 if (target.Length < source.Length) return false; foreach (int pos in positions) { if (source[pos] != target[pos]) return false; } return true; }
内容的提问来源于stack exchange,提问作者Adil15
相关产品推荐
相关产品推荐

