[英]get all ranges of a substring in a string in swift
我有一個字符串,例如“ab ad adk fda kla kad ab ab kd”。 我想獲得 ab 的所有范圍。(這里 ab 出現在 3 個位置,所以我應該得到 3 個范圍)。在正常情況下,我的代碼工作正常,但如果搜索文本是“.”,那么我得到的結果是錯誤的
do {
let regEx = try NSRegularExpression(pattern: searchText, options: NSRegularExpressionOptions.CaseInsensitive)
let matchesRanges = regEx.matchesInString(attributedText.string, options:[], range: NSMakeRange(0, attributedText.string.length))
for rng in matchesRanges {
let wordRange = rng.rangeAtIndex(0)
}
} catch {
...
}
以下解決方案使用原生 Swift 4 函數range(of:, options:, range:, locale:)
):
extension String {
func ranges(of substring: String, options: CompareOptions = [], locale: Locale? = nil) -> [Range<Index>] {
var ranges: [Range<Index>] = []
while ranges.last.map({ $0.upperBound < self.endIndex }) ?? true,
let range = self.range(of: substring, options: options, range: (ranges.last?.upperBound ?? self.startIndex)..<self.endIndex, locale: locale)
{
ranges.append(range)
}
return ranges
}
}
(然后 Swift 4 提供了原生 API 來從Range<Index>
轉換為NSRange
)
斯威夫特 5:
最受歡迎答案的改進版:
extension String {
func ranges(of substring: String, options: CompareOptions = [], locale: Locale? = nil) -> [Range<Index>] {
var ranges: [Range<Index>] = []
while let range = range(of: substring, options: options, range: (ranges.last?.upperBound ?? self.startIndex)..<self.endIndex, locale: locale) {
ranges.append(range)
}
return ranges
}
}
我會建議這樣的解決方案:
import Foundation
extension String {
func rangesOfString(s: String) -> [Range<Index>] {
let re = try! NSRegularExpression(pattern: NSRegularExpression.escapedPatternForString(s), options: [])
return re.matchesInString(self, options: [], range: nsRange(startIndex ..< endIndex)).flatMap { range($0.range) }
}
func range(nsRange : NSRange) -> Range<Index>? {
let utf16from = utf16.startIndex.advancedBy(nsRange.location, limit: utf16.endIndex)
let utf16to = utf16from.advancedBy(nsRange.length, limit: utf16.endIndex)
if let from = String.Index(utf16from, within: self),
let to = String.Index(utf16to, within: self)
{
return from ..< to
} else {
return nil
}
}
func nsRange(range : Range<Index>) -> NSRange {
let utf16from = String.UTF16View.Index(range.startIndex, within: utf16)
let utf16to = String.UTF16View.Index(range.endIndex, within: utf16)
return NSRange(location: utf16.startIndex.distanceTo(utf16from), length: utf16from.distanceTo(utf16to))
}
}
print("[^x]? [^x]? [^x]?".rangesOfString("[^x]?")) // [Range(0..<5), Range(6..<11), Range(12..<17)]
除了主要問題,這段代碼還展示了將NSRange
與Range<String.Index>
相互轉換的方法(基於這篇文章)。
您正在使用正則表達式,因此您需要注意具有特殊含義的字符 - .
只是其中之一。
如果您正在搜索子字符串,我建議改用舊的 rangeOf... 方法:
func rangeOfString(_ searchString: String,
options mask: NSStringCompareOptions,
range searchRange: NSRange) -> NSRange
只需繼續在您的字符串上調用該方法(並調整searchRange
),直到找不到更多匹配項。
您可以通過以下代碼獲取特定字符串的出現次數:
let str: NSMutableString = "ab ad adk fda kla kad ab ab kd"
let count = str.replaceOccurrencesOfString("ab", withString: "ab", options: NSStringCompareOptions.LiteralSearch, range: NSMakeRange(0, str.length))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.