This is really a wonderful problem and the shame that today it is not easy to do in Swift (someday it will be, but not today).
I hate this code, but I sit on the plane for 20 hours and do not have time to make it more pleasant. At least you can start using NSMutableString . It would be nice to work in String , and Swift hates regular expressions, so this is disgusting, but at least this is the beginning.
import Foundation let input = "Hello, World ... I 'ma newbie iOS Developer." let adjustments = [ (pattern: "\\s*(\\.\\.\\.|\\.|,)\\s*", replacement: "$1 "), // elipsis or period or comma has trailing space (pattern: "\\s*'\\s*", replacement: "'"), // apostrophe has no extra space (pattern: "^\\s+|\\s+$", replacement: ""), // remove leading or trailing space ] let mutableString = NSMutableString(string: input) for (pattern, replacement) in adjustments { let re = try! NSRegularExpression(pattern: pattern) re.replaceMatches(in: mutableString, options: [], range: NSRange(location: 0, length: mutableString.length), withTemplate: replacement) } mutableString // "Hello, World... I'm a newbie iOS Developer."
Regular expressions can be very confusing when you first encounter them. A few hints of reading them:
The specific language used by the Foundation is described by the ICU .
The backslash (\) means that the next character is special for regular expression. But inside the Swift line, a backslash means that the “next character is a special” line. Therefore you need to double them.
\ s means "space character"
\ s * means zero or more whitespace
\ s + means "one or more whitespace characters"
$ 1 means "the item we matched in parentheses"
| means "or"
^ means "start of line"
$ means end of line
. means "any character", so to indicate the "actual point" you must enter "\\". in the Swift line.
Please note that I check both "..." and ".". in the same regular expression. You kind of have to do something like this, otherwise "." will match three times in "...". Another approach was to first replace "..." with "..." (a single ellipsis character, typing on a Mac, pressing "Opt-"). Then "..." is a single-character punctuation. (You may also decide to redeploy all the ellipsis to point-to-point at the end of the process.)
Something like this is probably the way I do it in real life, do it and submit, but it can be painful / practice to try to build it like a turn-based state machine, going through one at a time, and tracking the current state.