所以,我在另一个字符串中获取字符串实例的方法是使用这个String类扩展:
func indexOf(target: String) -> Int? {
let range = (self as NSString).range(of: target)
guard range.toRange() != nil else {
return nil
}
return range.location
}
但是,现在我正在寻找一种方法来获取字符串中第n个字符串实例。例如,如果我想获得“House on the house House house strange people”中第3个“House”的索引。我该怎么做?
答案 0 :(得分:2)
直接在Swift String
上运行的可能解决方案,
没有桥接到NSString
(并且没有创建临时子串):
extension String {
func index(of target: String, instance: Int = 1) -> Int? {
precondition(!target.isEmpty)
precondition(instance > 0)
var found = 0 // Number of occurrences found so far.
var pos = startIndex // Current search position.
// Search for next occurrence of `target`.
while let r = range(of: target, range: pos..<endIndex) {
found += 1
// Are we done?
if found == instance {
// Distance in # of characters:
return distance(from: startIndex, to: r.lowerBound)
}
// Continue search after this occurrence.
pos = r.upperBound
}
return nil
}
}
示例:
let bStr = "Houses on the show Dr. House's PlayHouse house strange people"
let ls = "House"
if let idx = bStr.index(of: ls, instance: 3) {
print(idx) // 35
}
答案 1 :(得分:1)
我喜欢Martin R的答案,但我发现递归表达更直观。在我的实现中,我们实际返回Range(作为可选):
extension String {
typealias SRange = Range<String.Index>
func range(of target:String, options:String.CompareOptions, nth:Int) -> SRange? {
func helper(hnth:Int, range:SRange) -> SRange? {
let r = self.range(of: target, options: options, range: range)
if let r = r, hnth < nth {
return helper(hnth:hnth+1, range:r.upperBound..<self.endIndex)
}
return r
}
return helper(hnth:1, range: self.startIndex..<self.endIndex)
}
}
如果目标字符串出现nth
,则返回Swift Range,否则返回nil
。这是一个测试:
let s = "Houses on the show House house strange people."
let targ = "House"
let r = s.range(of: targ, options: .caseInsensitive, nth: 3)
// now r is an Optional wrapping 25..<30