快速字符串替换并获得新范围

时间:2018-07-24 07:04:25

标签: swift range

在替换字符串后检索范围的更好方法吗?

这是当前版本:

let username = "apple"
msgString = "{{user}} has an apple"
guard let range = msgString.range(of: "{{user}}") else { return }
msgString.replaceSubrange(range, with username)
userRange = msgString.range(of: username)

有什么更好的方法来获取用户名范围

4 个答案:

答案 0 :(得分:1)

我建议您创建一个类来做您多次做的事情

在此类中,您可以使用replace方法获取stringRange和newReplacedString:

class StringService {

  /** create an object to access every method because this class provides you services */

  static let shared = StringService()


  /** Service classes should not be available for creating instances */

  private init () {}


  func replace(mySting: String ,by: String, with: String) -> (String,Range<String.Index>?) {

     var newString = ""

     if let range = myString.range(of:by) {

        newString.replaceSubrange(range,with:with)

        return (newString,range)

      }esle{

        return ("",nil)

      }
  }

用法:

let replacedString = StringService.shared.replace(mySting: "myString is",
                                                  by: "is",
                                                  with: "was").0

if let replacedStringRange = StringService.shared.replace(mySting: "myString is",
                                                  by: "is",
                                                  with: "was").1 {

}

如果您想使用本机库,则可以使用:

"myString is".replacingOccurrences(of: "is",
                                   with: "was",
                                   options: .literal,
                                   range: nil)

答案 1 :(得分:0)

两个功能:

  • replacingOccurrences...返回一个新字符串并告知更改范围
  • replaceOccurrences...更改当前变量的值并通知更改范围

实现这些目标的最佳位置是String扩展名:

extension String {

    func replacingOccurrences<T: StringProtocol>(of toReplace: T,
                                                 with newString: T,
                                                 options: String.CompareOptions = [],
                                                 range searchRange: Range<T.Index>? = nil,
                                                 completion: ((Range<T.Index>?, Range<T.Index>?) -> Void)) -> String {

        let oldRange = range(of: toReplace)

        let replacedString = replacingOccurrences(of: toReplace,
                                                  with: newString,
                                                  options: options,
                                                  range: searchRange)

        let newRange = replacedString.range(of: newString)

        completion(oldRange, newRange)

        return replacedString
    }

    mutating func replaceOccurrences<T: StringProtocol>(of toReplace: T,
                                                        with newString: T,
                                                        options: String.CompareOptions = [],
                                                        range searchRange: Range<T.Index>? = nil,
                                                        completion: ((Range<T.Index>?, Range<T.Index>?) -> Void)) {

        self = replacingOccurrences(of: toReplace,
                                    with: newString,
                                    options: options,
                                    range: searchRange,
                                    completion: completion)
    }
}

用法:

let username = "apple"
var msgString = "{{user}} has an apple"

msgString.replaceOccurrences(of: "{{user}}", with: username) { (oldRange, newRange) in
    print(oldRange)
    print(newRange)
}

答案 2 :(得分:0)

让我们从您提供的代码的更正版本开始:

let username = "apple"
var msgString = "{{user}} has an apple"
guard let range = msgString.range(of: "{{user}}") else { return }
msgString.replaceSubrange(range, with: username)

在这里,我们在msgString中将"{{user}}"替换为"apple"。问题是:"apple"中的msgString的范围是多少?

当您意识到我们已经知道答案时,解决方案很简单。它分为两个部分:

  • 新范围从旧范围开始的同一位置开始。这就是说新范围的下限与旧范围的下限相同。我们已经知道那是什么了:range.lowerBound

  • 新范围的长度是替换字符串的长度。表示为count

因此,所需范围是:

let newRange = 
    range.lowerBound..<msgString.index(range.lowerBound, offsetBy: username.count)

如果我们要做很多这样的事情,扩展String可能会很好。例如:

extension String {
    mutating func replaceSubrangeAndReportNewRange (
        _ bounds: Range<String.Index>, with s: String
        ) -> Range<String.Index> {
            self.replaceSubrange(bounds, with:s)
            return bounds.lowerBound..<self.index(bounds.lowerBound, offsetBy:s.count)
    }
}

答案 3 :(得分:-1)

Swift 4.0

您可以使用replacingOccurrences方法替换文本。

  msgString.replacingOccurrences(of: "{{user}}", with: "apple", options: .literal, range: nil)

输出:

apple has an apple