在 Swift 中的字符串中查找第 N 个子字符串实例的索引
Find index of Nth instance of substring in string in Swift
我的 Swift 应用涉及在 UITextView 中搜索文本。用户可以在该文本视图中搜索某个子字符串,然后跳转到文本视图中该字符串的任何实例(例如,第三个实例)。我需要找出它们所在字符的整数值。
例如:
示例 1: 用户搜索 "hello",文本视图显示为 "hey hi hello, hey hi hello",然后用户按下向下箭头以查看第二个实例。我需要知道第二个 hello 中第一个 h
的整数值(即 hello 中的哪个#字符在文本视图中)。整数值应为 22
.
示例 2: 用户搜索 "abc" 而文本视图读取 "abcd" 并且他们正在寻找 [=13= 的第一个实例],所以整数值应该是 1
(这是 a
的整数值,因为它是他们正在搜索的实例的第一个字符)。
如何获取用户搜索的字符索引?
Xcode 11 • Swift 5 或更高版本
let sentence = "hey hi hello, hey hi hello"
let query = "hello"
var searchRange = sentence.startIndex..<sentence.endIndex
var indices: [String.Index] = []
while let range = sentence.range(of: query, options: .caseInsensitive, range: searchRange) {
searchRange = range.upperBound..<searchRange.upperBound
indices.append(range.lowerBound)
}
print(indices) // "[7, 21]\n"
另一种方法是 NSRegularExpression
,它旨在轻松地遍历字符串中的匹配项。如果您使用 .ignoreMetacharacters
选项,它不会应用任何复杂的 wildcard/regex 逻辑,而只会查找有问题的字符串。所以考虑:
let string = "hey hi hello, hey hi hello" // string to search within
let searchString = "hello" // string to search for
let matchToFind = 2 // grab the second occurrence
let regex = try! NSRegularExpression(pattern: searchString, options: [.caseInsensitive, .ignoreMetacharacters])
您可以使用 enumerateMatches
:
var count = 0
let range = NSRange(string.startIndex ..< string.endIndex, in: string)
regex.enumerateMatches(in: string, range: range) { result, _, stop in
count += 1
if count == matchToFind {
print(result!.range.location)
stop.pointee = true
}
}
或者你可以用 matches(in:range:)
找到所有的,然后抓取第 n 个:
let matches = regex.matches(in: string, range: range)
if matches.count >= matchToFind {
print(matches[matchToFind - 1].range.location)
}
显然,如果您愿意,可以省略 .ignoreMetacharacters
选项并允许用户执行正则表达式搜索(例如通配符、全词搜索、单词开头等)。
对于 Swift 2,请参阅 previous revision of this answer。
我的 Swift 应用涉及在 UITextView 中搜索文本。用户可以在该文本视图中搜索某个子字符串,然后跳转到文本视图中该字符串的任何实例(例如,第三个实例)。我需要找出它们所在字符的整数值。
例如:
示例 1: 用户搜索 "hello",文本视图显示为 "hey hi hello, hey hi hello",然后用户按下向下箭头以查看第二个实例。我需要知道第二个 hello 中第一个 h
的整数值(即 hello 中的哪个#字符在文本视图中)。整数值应为 22
.
示例 2: 用户搜索 "abc" 而文本视图读取 "abcd" 并且他们正在寻找 [=13= 的第一个实例],所以整数值应该是 1
(这是 a
的整数值,因为它是他们正在搜索的实例的第一个字符)。
如何获取用户搜索的字符索引?
Xcode 11 • Swift 5 或更高版本
let sentence = "hey hi hello, hey hi hello"
let query = "hello"
var searchRange = sentence.startIndex..<sentence.endIndex
var indices: [String.Index] = []
while let range = sentence.range(of: query, options: .caseInsensitive, range: searchRange) {
searchRange = range.upperBound..<searchRange.upperBound
indices.append(range.lowerBound)
}
print(indices) // "[7, 21]\n"
另一种方法是 NSRegularExpression
,它旨在轻松地遍历字符串中的匹配项。如果您使用 .ignoreMetacharacters
选项,它不会应用任何复杂的 wildcard/regex 逻辑,而只会查找有问题的字符串。所以考虑:
let string = "hey hi hello, hey hi hello" // string to search within
let searchString = "hello" // string to search for
let matchToFind = 2 // grab the second occurrence
let regex = try! NSRegularExpression(pattern: searchString, options: [.caseInsensitive, .ignoreMetacharacters])
您可以使用 enumerateMatches
:
var count = 0
let range = NSRange(string.startIndex ..< string.endIndex, in: string)
regex.enumerateMatches(in: string, range: range) { result, _, stop in
count += 1
if count == matchToFind {
print(result!.range.location)
stop.pointee = true
}
}
或者你可以用 matches(in:range:)
找到所有的,然后抓取第 n 个:
let matches = regex.matches(in: string, range: range)
if matches.count >= matchToFind {
print(matches[matchToFind - 1].range.location)
}
显然,如果您愿意,可以省略 .ignoreMetacharacters
选项并允许用户执行正则表达式搜索(例如通配符、全词搜索、单词开头等)。
对于 Swift 2,请参阅 previous revision of this answer。