在Swift中查找字符串中第N个子串实例的索引

owl*_*ipe 5 string ios swift swift2

我的Swift应用程序涉及在UITextView中搜索文本.用户可以在该文本视图中搜索某个子字符串,然后在文本视图中跳转到该字符串的任何实例(例如,第三个实例).我需要找出它们所在的字符的整数值.

例如:

示例1:用户搜索"hello"并且文本视图显示"hey hi hello,hey hi hello",然后用户按下箭头以查看第二个实例.我需要知道h第二个hello中第一个的整数值(即hello中的哪个#字符在文本视图中).整数值应该是22.

示例2:当文本视图读取"abcd"并且他们正在查找第一个实例时abc,用户搜索"abc" ,因此整数值应该是1(a因为它是实例的第一个字符,所以它的整数值他们正在寻找).

如何获取用户正在搜索的字符的索引?

Leo*_*bus 10

试试这样:

let sentence = "hey hi hello, hey hi hello"
let query = "hello"
var searchRange = sentence.startIndex..<sentence.endIndex
var indexes: [String.Index] = []

while let range = sentence.rangeOfString(query, options: .CaseInsensitiveSearch, range: searchRange) {
    searchRange = range.endIndex..<searchRange.endIndex
    indexes.append(range.startIndex)
}

print(indexes)   // "[7, 21]\n"
Run Code Online (Sandbox Code Playgroud)

Xcode 8 beta 6•Swift 3

while let range = sentence.range(of: query, options: .caseInsensitive, range: searchRange) {
    searchRange = range.upperBound..<searchRange.upperBound
    indexes.append(range.lowerBound)
}
Run Code Online (Sandbox Code Playgroud)


Rob*_*Rob 5

另一种方法NSRegularExpression旨在轻松地迭代字符串中的匹配项。如果您使用该.ignoreMetacharacters选项,它不会应用任何复杂的通配符/正则表达式逻辑,而只会查找有问题的字符串。所以考虑:

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])
Run Code Online (Sandbox Code Playgroud)

你可以使用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
    }
}
Run Code Online (Sandbox Code Playgroud)

或者你可以找到所有这些matches(in:range:),然后抓住第 n 个:

let matches = regex.matches(in: string, range: range)
if matches.count >= matchToFind {
    print(matches[matchToFind - 1].range.location)
}
Run Code Online (Sandbox Code Playgroud)

显然,如果您愿意,您可以省略该.ignoreMetacharacters选项并允许用户也执行正则表达式搜索(例如通配符、全字搜索、单词开头等)。

对于 Swift 2,请参阅此答案的先前修订版