在swift中获得一个string的所有范围
我有一个string,例如“ab ad adk fda kla kad ab ab kd”。 我想要得到ab的所有范围(这里ab是在3的位置,所以我应该得到3范围)。在正常情况下我的代码工作正常,但如果search文本是“。”,那么我得到错误的结果
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 { }
你正在使用正则expression式,所以你需要关心具有特殊含义的字符.
只是其中之一。
如果你正在search子string,我build议使用旧的rangeOf …方法:
func rangeOfString(_ searchString: String, options mask: NSStringCompareOptions, range searchRange: NSRange) -> NSRange
只要继续在你的string上调用该方法(并调整searchRange
),直到找不到进一步的匹配。
我会build议这样一个解决scheme:
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>
(基于这篇文章 )。
您可以通过以下代码获得特定string的发生次数:
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))
以下解决scheme使用本地Swift 4函数range(of:, options:, range:, locale:)
:: range(of:, options:, range:, locale:)
):
extension String { func ranges(of substring: String, options: CompareOptions = [], locale: Locale? = nil) -> [Range<Index>] { var ranges: [Range<Index>] = [] while 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
)