Mutating function for replacingOccurrences(of:with:)

Dear SE,

When I have a string where I want to replace occurrences of a string with another, I have to use the following:

var str = "Hello, playground"
str = str.replacingOccurrences(of: "Hello", with: "Goodbye")

Sometimes, I found this can get very repetitive, especially if my variable name is long and I need to do multiple replacements.

I found that many developers on StackOverflow, including myself, suggest that one should create an extension to mimic a mutating version of the function. This extension will also remove the overhead of copying the original string. I believe adding a mutating version of the function would be a great addition to the standard library.

extension String {
    mutating func replaceOccurrences(of target: String, with replacement: String, options: String.CompareOptions = [], locale: Locale? = nil) {
        var range: Range<String.Index>?
        repeat {
            range = self.range(of: target, options: options, range: range.map { $0.lowerBound..<self.endIndex }, locale: locale)
            if let range = range {
                self.replaceSubrange(range, with: replacement)
            }
        } while range != nil
    }
}

I would also be interested in your comments on allowing the target to include multiple strings to be substituted by a single replacement. This would be especially useful when I need to replace multiple targets with simply “”. Potentially removeOccurrences(of target: String).

5 Likes

Seems like a worthwhile thing to look into. There are plenty of mutating/non-mutating pairs on swift types and this one in particular is something I'm sure has bothered many people (myself included).

Note that this isn't a Swift standard library method, and it is only present if you import Foundation due to NSString bridging and this method. There is a big overhaul of String processing in Swift planned, including regular expressions, that will probably touch on this area. You can read about some of the ideas in @Michael_Ilseman's State of String: ABI, Performance, Ergonomics, and You!, including a link to @Chris_Lattner3's stated goal for Swift to be “better at string processing than Perl”.

5 Likes

This method actually exists already, but on NSMutableString.

@lancep is working on Subsequence-based find/replace, which would extend this functionality to all (perhaps-Bidirectional)Collections.

edit: Here's the pitch: Range based Collection mutations

1 Like