我有一个字符串,例如“ab ad adk fda kla kad ab ab kd”。我希望获得所有范围的ab。(这里ab出现在3个位置,所以我应该得到3个范围)。在正常的情况下我的代码工作正常,但如果搜索文本是“。”,那么我得到错误的结果< / p>
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 {
...
}
答案 0 :(得分:11)
以下解决方案使用原生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
)
答案 1 :(得分:3)
我会建议这样的解决方案:
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>
的方法(基于this post)。
答案 2 :(得分:1)
您正在使用正则表达式,因此您需要注意具有特殊含义的字符 - .
只是其中之一。
如果您正在搜索子字符串,我建议使用旧的rangeOf ...方法代替:
func rangeOfString(_ searchString: String,
options mask: NSStringCompareOptions,
range searchRange: NSRange) -> NSRange
只需在字符串上调用该方法(并调整searchRange
),直到找不到更多匹配项。
答案 3 :(得分:1)
快捷键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
}
}
答案 4 :(得分:0)
您可以通过以下代码获取特定字符串的出现次数:
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))