如何在swift2中找到另一个字符串中一个字符串的所有位置?

时间:2015-08-29 11:16:31

标签: string swift

我可以通过使用下面的代码在myString“ATGGACGTGAGCTGATCGATGGCTGAAATGAAAA”中找到字符串“ATG”的第一个位置(即索引范围是0 ...< 3)。问题是如何找到“ATG”的所有位置,而不仅仅是myString中的第一个位置。

let stringRange = myString.rangeOfString("ATG")

4 个答案:

答案 0 :(得分:13)

您可以使用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,因为它以第一个范围内的字符开头。

答案 1 :(得分:5)

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 []
        }
    }
}

答案 2 :(得分:2)

欢迎来到SO。

这将是一个很好的编程练习。我建议你把它作为一个学习项目。

编写一个需要搜索字符串的函数和一个要搜索的字符串,并返回一个可选的NSRange对象数组。如果没有找到任何匹配项,则可选项将为nil。或者,您可以始终返回一个数组,但如果找不到该字符串,则包含0个NSRange对象。

让您的函数使用NSString方法rangeOfString:options:range:来搜索字符串。首先,您将搜索整个源字符串。找到第一个匹配项后,您将调整range参数,以便仅在该事件发生后搜索源字符串的其余部分。

编辑:

这样做的一种优雅方式是作为String类的扩展。这样您就可以使用新方法,就像它是String s。

的内置功能一样

答案 3 :(得分:1)

这是有道理的,因为according to the docsrangeOfString:

  

查找并返回接收者中给定字符串第一次出现的范围。

如果你想找到所有的出现次数,你可以循环直到rangeOfString:返回nil,并且每次将字符串修剪到匹配范围之后。当然,您必须跟踪原始字符串中的位置并转换索引。