如何替换字符串中出现的次数有限

时间:2018-06-22 17:09:33

标签: swift

假设我有字符串"blabla[R]bla[R]blaaa[R]blabla[R]bla[R]bla"

常规replacingOccurrences替换所有出现的内容。我只想替换3。

newString = myString.replacingOccurrences(of: "[R]", with: "(X)")

得出结果"blabla(X)bla(X)blaaa(X)blabla[R]bla[R]bla"

2 个答案:

答案 0 :(得分:4)

您可以获取该字符串的前3个范围,然后以相反的顺序迭代范围,以替换子范围:

var string = "blabla[R]bla[R]blaaa[R]blabla[R]bla[R]bla"
var ranges: [Range<String.Index>] = []
var start = string.startIndex
while start < string.endIndex, 
    let range = string.range(of: "[R]", range: start..<string.endIndex) {
    ranges.append(range)
    start = range.upperBound
    if ranges.count == 3 { break }
}

for range in ranges.reversed() {
    string.replaceSubrange(range, with:  "(X)")
}
print(string)  // blabla(X)bla(X)blaaa(X)blabla[R]bla[R]bla

答案 1 :(得分:1)

这是String的有用扩展,它为count添加了replacingOccurrences参数。这包括对范围和选项(例如,向后)的支持。

extension String {
    func replacingOccurrences<Target, Replacement>(of target: Target, with replacement: Replacement, count: Int, options: String.CompareOptions = [], range searchRange: Range<String.Index>? = nil) -> String where Target : StringProtocol, Replacement : StringProtocol {
        var matches = [Range<String.Index>]()
        var sRange = searchRange ?? Range(startIndex..<endIndex)
        while matches.count < count && !sRange.isEmpty {
            if let mRange = range(of: target, options: options, range: sRange, locale: nil) {
                matches.append(mRange)
                if options.contains(.backwards) {
                    sRange = Range(sRange.lowerBound..<mRange.lowerBound)
                } else {
                    sRange = Range(mRange.upperBound..<sRange.upperBound)
                }
            } else {
                break
            }
        }

        var res = self
        for range in matches.sorted(by: { $0.lowerBound > $1.lowerBound }) {
            res.replaceSubrange(range, with: replacement)
        }
        return res
    }
}

let test = "blabla[R]bla[R]blaaa[R]blabla[R]bla[R]bla"
let res1 = test.replacingOccurrences(of: "[R]", with: "(x)", count: 3)
print(res1)
let res2 = test.replacingOccurrences(of: "[R]", with: "(x)", count: 3, options: [ .backwards ])
print(res2)

输出:

  

blabla(x)bla(x)blaaa(x)blabla [R] bla [R] bla
  blabla [R] bla [R] blaaa(x)blabla(x)bla(x)bla