如何检测两个Range<String.Index>类型的范围是否连续
检测两个Range<String.Index>是否连续的方法
你的当前实现的优缺点
你现在通过将Range<String.Index>转换为NSRange,再用previousNSRange.upperBound + 1 == currentNSRange.lowerBound判断的方法是可行的,但有个需要注意的点:Swift的String.Index是基于Unicode标量的位置,而NSRange是基于UTF-16编码的码元位置,如果字符串包含多字节Unicode字符(比如emoji、部分生僻汉字),直接转换可能出现索引不匹配的问题,导致判断结果出错。
更安全的Swift原生实现
不需要依赖Foundation框架的NSRange,直接用Swift字符串的原生API就能准确判断,而且避免编码转换的坑:
核心逻辑是:判断第一个范围的upperBound的下一个位置,是否等于第二个范围的lowerBound。
代码示例
func rangesAreConsecutive(_ range1: Range<String.Index>, _ range2: Range<String.Index>, in string: String) -> Bool { // 可选校验:确保两个范围都属于当前字符串,避免越界或跨字符串比较 guard string.contains(range1) && string.contains(range2) else { return false } // 判断range1的下一个索引是否等于range2的起始索引 return string.index(after: range1.upperBound) == range2.lowerBound } // 测试对应你的示例场景 let testString = String(repeating: "a", count: 100) // 示例1:{0,50} 与 {51,17} → 连续 let range1 = testString.startIndex..<testString.index(testString.startIndex, offsetBy: 50) let range2Consecutive = testString.index(testString.startIndex, offsetBy: 51)..<testString.index(testString.startIndex, offsetBy: 51+17) print(rangesAreConsecutive(range1, range2Consecutive, in: testString)) // 输出 true // 示例2:{0,50} 与 {52,17} → 不连续 let range2NonConsecutive1 = testString.index(testString.startIndex, offsetBy: 52)..<testString.index(testString.startIndex, offsetBy: 52+17) print(rangesAreConsecutive(range1, range2NonConsecutive1, in: testString)) // 输出 false // 示例3:{0,50} 与 {56,17} → 不连续 let range2NonConsecutive2 = testString.index(testString.startIndex, offsetBy: 56)..<testString.index(testString.startIndex, offsetBy: 56+17) print(rangesAreConsecutive(range1, range2NonConsecutive2, in: testString)) // 输出 false
两种方法的适用场景
- 如果你的字符串都是ASCII字符,转换为
NSRange的方法可以正常工作,但原生方法更通用。 - 如果需要处理包含复杂Unicode字符的字符串,优先选择Swift原生实现,避免编码转换带来的错误。
内容的提问来源于stack exchange,提问作者Hassan Taleb
相关产品推荐
相关产品推荐

