我可以使用以下代码在myString "ATGGACGTGAGCTGATCGATGGCTGAAATGAAAA"中找到字符串“ATG”的第一个位置(即索引范围为0..<3)。问题是如何找到myString中所有的“ATG”位置,而不仅仅是第一个。
let stringRange = myString.rangeOfString("ATG")
NSRegularExpression
来查找字符串的所有出现:
Swift 1.2:let mystr = "ATGGACGTGAGCTGATCGATGGCTGAAATGAAAA"
let searchstr = "ATG"
let ranges: [NSRange]
// Create the regular expression.
if let regex = NSRegularExpression(pattern: searchstr, options: nil, error: nil) {
// Use the regular expression to get an array of NSTextCheckingResult.
// Use map to extract the range from each result.
ranges = regex.matchesInString(mystr, options: nil, range: NSMakeRange(0, count(mystr))).map {$0.range}
} else {
// There was a problem creating the regular expression
ranges = []
}
println(ranges) // prints [(0,3), (18,3), (27,3)]
Swift 2:
let mystr = "ATGGACGTGAGCTGATCGATGGCTGAAATGAAAA"
let searchstr = "ATG"
let ranges: [NSRange]
do {
// Create the regular expression.
let regex = try NSRegularExpression(pattern: searchstr, options: [])
// Use the regular expression to get an array of NSTextCheckingResult.
// Use map to extract the range from each result.
ranges = regex.matchesInString(mystr, options: [], range: NSMakeRange(0, mystr.characters.count)).map {$0.range}
}
catch {
// There was a problem creating the regular expression
ranges = []
}
print(ranges) // prints [(0,3), (18,3), (27,3)]
Swift 3: 使用 Swift 原生的 Range
类型。
let mystr = "ATGGACGTGAGCTGATCGATGGCTGAAATGAAAA"
let searchstr = "ATG"
do {
// Create the regular expression.
let regex = try NSRegularExpression(pattern: searchstr, options: [])
// Use the regular expression to get an array of NSTextCheckingResult.
// Use map to extract the range from each result.
let fullStringRange = mystr.nsRange(from: mystr.startIndex ..< mystr.endIndex)
let matches = regex.matches(in: mystr, options: [], range: fullStringRange)
let ranges = matches.map {$0.range}
print(ranges) // prints [(0,3), (18,3), (27,3)]
}
catch {}
注意:
"+*()[].{}?\^$"
),则它将不能按预期工作。您可以预处理搜索字符串以添加转义字符来抵消这些字符的特殊含义,但这可能比价值更高。mystr
是 "AAAA"
而 searchstr
是 "AA"
时,另一个限制可以演示出来。在这种情况下,该字符串仅被找到两次。中间的 AA 不会被找到,因为它以属于第一个范围的字符开头。extension String {
public func rangesOfString(searchString:String, options: NSStringCompareOptions = [], searchRange:Range<Index>? = nil ) -> [Range<Index>] {
if let range = rangeOfString(searchString, options: options, range:searchRange) {
let nextRange = Range(start:range.endIndex, end:self.endIndex)
return [range] + rangesOfString(searchString, searchRange: nextRange)
} else {
return []
}
}
}
let nextRange = range.startIndex.advancedBy(1)..<self.endIndex
。 - Sean Vikoren这是有道理的,因为根据文档rangeOfString:的说明:
查找并返回接收器中给定字符串的第一个匹配项的范围。
如果您想要查找所有出现的情况,可以循环直到rangeOfString:
返回nil,并且每次都将字符串修剪到与匹配范围相同。当然,您必须在原始字符串中跟踪您的位置并转置索引。
欢迎来到SO。
这将是一个很好的编程练习。我建议您将其作为学习项目进行。
编写一个函数,该函数接受要搜索的字符串和要搜索的字符串,并返回可选的NSRange对象数组。如果找不到任何匹配项,则可选项将为nil。或者,您可以始终返回一个数组,但如果未找到字符串,则将其包含0个NSRange对象。
让您的函数使用NSString方法rangeOfString:options:range:来搜索字符串。首先,您将搜索整个源字符串。一旦找到第一个匹配项,您将调整范围参数,以仅在该匹配项之后搜索源字符串的剩余部分。
一种优雅的方法是将其作为String类的扩展来完成。这样,您可以像使用String的内置功能一样使用新方法。
NSRegularExpression
使用方法(投票)。然而,ranges
变量的作用域是否仅限于if let
(Swift 1.2)或do
(Swift 2)的大括号内部,而无法在外部访问?为了使其有用,我认为您需要将ranges
定义为类型为[NSRange]?
的数组,并将其定义在外部作用域。 - Duncan Cvar ranges = [NSRange]()
。这将分配一个新的、空的NSRange对象数组,然后被调用matchesInString
返回的数组所替换。创建一个被替换的空范围没有意义。最好使用var ranges = [NSRange]!
将其设置为隐式解包可选项,但不要创建空数组。这可以节省一个可抛弃的对象创建。 - Duncan Cmystr.unicodeScalars.count
来计算单个Unicode字符而不仅仅是字形。 - sharshi