Reputation: 473
I am looking to run a quick function in Swift to change certain aspects of a string.
Objective: Take input string [UITextField] and replace all punctuation followed by a space (. ) or (? ) with just the punctuation be itself within the string
Problem: I do not know what the punctuation will be. There is a UITextField for the user to enter this in. This textfield is used for other functions as well.
Example: Input: Hello, how are you doing? I am doing fine. Thank you. Output: Hello,how are you doing?I am doing fine.Thank you.
Test Code: I also have a Swift Stub (JSFiddle for Swift) if you want to test in browser.
var inputText = "hello, how are you doing? I am okay. Thanks." // User input from UITextField
var newString: String! // Setting string for global variable
var punctuation: String = "" // Starts as blank, could remain empty
punctuation = "?.," // Dont know what this will be. Input from UITextField
var characters = Array(punctuation)
println(characters) //Testing in console
//Current idea but does not work as needed
func replacePunctuationSpace() -> String{
for character in characters{
newString = inputText.stringByReplacingOccurrencesOfString("\(character) ", withString: "\(character)")
println("Replacing \(character) ... \(newString)")
}
return newString
}
replacePunctuationSpace()
//Only replaces last item in array
println(newString)
Please let me know if something doesn't make sense.
Thanks for the help. Eric
Upvotes: 0
Views: 1819
Reputation: 131491
You should be able to use an NSRegularExpression and a method like
replaceMatchesInString:options:range:withTemplate:
.
I am no expert on regular expressions. I believe that you can make your regular expression have 2 "capture groups" where the first capture group is a list of possible punctuation characters, and the second is a variable amount of whitespace. Your template would tell the `replaceMatchesInString:options:range:withTemplate: function to replace each matched expression with the just the contents of the first capture group (the matched punctuation symbol.)
You will need to list all the punctuation symbols that you want to handle (e.g. ".,:?!;")
I decided to use this as a learning experience to learn more about regular expressions.
I found this page that is a decent introduction to regular expressions.
Then I read the docs on NSRegularExpression, and in particular, the stringByReplacingMatchesInString
function. That says that the string is replaced based on a "template".
It seems that the parts of a regular expression can be divided into "capture groups", or sections that get matched separately. You can then use those capture groups to use parts of the matched string to the output of stringByReplacingMatchesInString.
Here is some playground code I wrote that searches for the punctuation characters ",.:;?!" followed by one or more whitespace characters and replaces them with just the punctuation, stripping away the whitespace:
var error: NSError?
let myRegEx = NSRegularExpression(pattern: "([,.:;?!])(\\s*)",
options: NSRegularExpressionOptions(0),
error: &error)
let testString = "This is a string, with some text. It has punctuation; can we replace that punctuation? I need to know what happens! "
let range = NSRange(location: 0, length: count(testString))
println(testString)
if let newString = myRegEx?.stringByReplacingMatchesInString(
testString,
options: NSMatchingOptions(0),
range: range,
withTemplate: "$1")
{
println("Result string = \(newString)")
}
else
{
println("No matches")
}
Apparently you create capture groups by enclosing part of your regular expression in parentheses. So I defined a regular expression with 2 capture groups. The first capture group is a "character class" that means any of the punctuation symbols: ,.:;?!
. That part of the regular expression looks like this: ([,.:;?!])
.
The second capture group matches any number of whitespace characters. The special "character class" for whitespace is \s
. However, Swift strings also use a backslash for escaping, so in order to get a literal backslash in the regular expression, I had to write it as \\s
. Putting that in parenthesis turns it into a capture group: (\\s)
.
In the call to stringByReplacingMatchesInString
the regular expression is ([,.:;?!])(\\s*)
and the template string is "$1".
That means:
Match strings that consist of a punctuation character followed by zero or more whitespace characters. Put the punctuation character of each match in "capture group" 1, and the whitespace in capture group 2".
Replace each match with the contents of capture group 1, which is the punctuation character.
That has the effect of discarding the whitespace from capture group 2, thus getting rid of whitespace after the specified punctuation characters.
Upvotes: 3
Reputation: 6416
Disclaimer: I have never written Swift
The issue is that you are only ever modifying the inputText
variable. Each iteration of your loop is starting over with the original input text.
Try something like this:
var inputText = "hello, how are you doing? I am okay. Thanks." // User input from UITextField
var newString: String! // Setting string for global variable
var punctuation: String = "" // Starts as blank, could remain empty
punctuation = "?.," // Dont know what this will be. Input from UITextField
var characters = Array(punctuation)
println(characters) //Testing in console
//Current idea but does not work as needed
func replacePunctuationSpace() -> String {
newString = inputText
for character in characters{
newString = newString.stringByReplacingOccurrencesOfString("\(character) ", withString: "\(character)")
println("Replacing \(character) ... \(newString)")
}
return newString
}
replacePunctuationSpace()
//Only replaces last item in array
println(newString)
http://swiftstub.com/716967254/
Upvotes: 1
Reputation: 540065
This can (for example) be achieved with NSScanner
. The following
code should be self-explaining :)
let inputText = "hello, how are you doing? I am okay. Thanks."
var outputText = ""
let punkt = NSCharacterSet.punctuationCharacterSet()
let space = NSCharacterSet.whitespaceCharacterSet()
let scanner = NSScanner(string: inputText)
while !scanner.atEnd {
var tmp : NSString?
if scanner.scanUpToCharactersFromSet(punkt, intoString: &tmp) {
outputText += tmp as! String
if scanner.scanCharactersFromSet(punkt, intoString: &tmp) {
outputText += tmp as! String
scanner.scanCharactersFromSet(space, intoString: nil)
}
}
}
println(outputText)
// hello,how are you doing?I am okay.Thanks.
Upvotes: 2