582

I am looking for a way to replace characters in a Swift String.

Example: "This is my string"

I would like to replace " " with "+" to get "This+is+my+string".

How can I achieve this?

Josh Correia
  • 3,807
  • 3
  • 33
  • 50
user3332801
  • 5,923
  • 2
  • 12
  • 5

24 Answers24

1079

This answer has been updated for Swift 4 & 5. If you're still using Swift 1, 2 or 3 see the revision history.

You have a couple of options. You can do as @jaumard suggested and use replacingOccurrences()

let aString = "This is my string"
let newString = aString.replacingOccurrences(of: " ", with: "+", options: .literal, range: nil)

And as noted by @cprcrack below, the options and range parameters are optional, so if you don't want to specify string comparison options or a range to do the replacement within, you only need the following.

let aString = "This is my string"
let newString = aString.replacingOccurrences(of: " ", with: "+")

Or, if the data is in a specific format like this, where you're just replacing separation characters, you can use components() to break the string into and array, and then you can use the join() function to put them back to together with a specified separator.

let toArray = aString.components(separatedBy: " ")
let backToString = toArray.joined(separator: "+")

Or if you're looking for a more Swifty solution that doesn't utilize API from NSString, you could use this.

let aString = "Some search text"

let replaced = String(aString.map {
    $0 == " " ? "+" : $0
})
shreyasm-dev
  • 2,711
  • 5
  • 16
  • 34
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
  • 11
    **options** and **range** parameters are optional – cprcrack Jan 15 '15 at 16:16
  • I don't know if I'm doing something wrong but the second swift 2.0 solution leaves me with and optional string. Original String looks like this: `"x86_64"` and the new mapping looks like `"Optional([\"x\", \"8\", \"6\", \"_\", \"6\", \"4\"])"` – John Shelley Oct 19 '15 at 15:07
  • @JohnShelley I'm unable to reproduce that. I'm not sure what's going on with the escaping, and this should be using String's `public init(_ characters: String.CharacterView)` initializer, which isn't failable. Are you trying this in a playground? I've had playgrounds give me strange output before that didn't match the output from an actually application. – Mick MacCallum Oct 19 '15 at 18:48
  • Nope, trying in a workspace/project. It might be something I'm doing, but thought I'd leave a comment just in case its common. – John Shelley Oct 19 '15 at 19:00
  • 8
    For anyone who had issues with using `stringByReplacingOccurrencesOfString` in Swift 2, you need to `import Foundation` to be able to use that method. – Liron Yahdav Nov 08 '15 at 03:40
  • 1
    wow, stringByReplacingOccurrencesOfString, how intuitive! I was expecting something like makeNewStringByReplacingOccurrencesOfFirstArgumentByValueInSecondArgument – Novellizator Mar 17 '16 at 16:10
  • For Swift 3, use `let newString = aString.replacingOccurrences(of: " ", with: "+")` – Mark A. Durham Oct 27 '16 at 20:51
  • Don't forget to `import Foundation` if you're doing this in a Playground. – maahd Oct 31 '19 at 09:22
74

You can use this:

let s = "This is my string"
let modified = s.replace(" ", withString:"+")    

If you add this extension method anywhere in your code:

extension String
{
    func replace(target: String, withString: String) -> String
    {
       return self.stringByReplacingOccurrencesOfString(target, withString: withString, options: NSStringCompareOptions.LiteralSearch, range: nil)
    }
}

Swift 3:

extension String
{
    func replace(target: String, withString: String) -> String
    {
        return self.replacingOccurrences(of: target, with: withString, options: NSString.CompareOptions.literal, range: nil)
    }
}
Jonas Franz
  • 555
  • 1
  • 8
  • 18
whitneyland
  • 10,632
  • 9
  • 60
  • 68
  • 2
    I would not name the function "replace" as this suggest it mutates the variable. Use same grammar as Apple do. Calling it "replacing(_:withString:)" makes it much more clear. A future mutating "replace" function would also conflict in naming. – Sunkas Apr 24 '19 at 12:44
69

Swift 3, Swift 4, Swift 5 Solution

let exampleString = "Example string"

//Solution suggested above in Swift 3.0
let stringToArray = exampleString.components(separatedBy: " ")
let stringFromArray = stringToArray.joined(separator: "+")

//Swiftiest solution
let swiftyString = exampleString.replacingOccurrences(of: " ", with: "+")
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
Ben Sullivan
  • 2,134
  • 1
  • 18
  • 32
22

Did you test this :

var test = "This is my string"

let replaced = test.stringByReplacingOccurrencesOfString(" ", withString: "+", options: nil, range: nil)
jaumard
  • 8,202
  • 3
  • 40
  • 63
18
var str = "This is my string"

print(str.replacingOccurrences(of: " ", with: "+"))

Output is

This+is+my+string
Jaykant
  • 349
  • 4
  • 11
14

Swift 5.5

I am using this extension:

extension String {

    func replaceCharacters(characters: String, toSeparator: String) -> String {
        let characterSet = CharacterSet(charactersIn: characters)
        let components = components(separatedBy: characterSet)
        let result = components.joined(separator: toSeparator)
        return result
    }

    func wipeCharacters(characters: String) -> String {
        return self.replaceCharacters(characters: characters, toSeparator: "")
    }
}

Usage:

"<34353 43434>".replaceCharacters(characters: "< >", toSeparator:"+") // +34353+43434+
"<34353 43434>".wipeCharacters(characters: "< >") // 3435343434
Ramis
  • 13,985
  • 7
  • 81
  • 100
12

Swift 4:

let abc = "Hello world"

let result = abc.replacingOccurrences(of: " ", with: "_", 
    options: NSString.CompareOptions.literal, range:nil)

print(result :\(result))

Output:

result : Hello_world
clemens
  • 16,716
  • 11
  • 50
  • 65
Manish
  • 184
  • 2
  • 9
8

A Swift 3 solution along the lines of Sunkas's:

extension String {
    mutating func replace(_ originalString:String, with newString:String) {
        self = self.replacingOccurrences(of: originalString, with: newString)
    }
}

Use:

var string = "foo!"
string.replace("!", with: "?")
print(string)

Output:

foo?
Josh Adams
  • 343
  • 3
  • 6
7

A category that modifies an existing mutable String:

extension String
{
    mutating func replace(originalString:String, withString newString:String)
    {
        let replacedString = self.stringByReplacingOccurrencesOfString(originalString, withString: newString, options: nil, range: nil)
        self = replacedString
    }
}

Use:

name.replace(" ", withString: "+")
Sunkas
  • 9,542
  • 6
  • 62
  • 102
7

Swift 3 solution based on Ramis' answer:

extension String {
    func withReplacedCharacters(_ characters: String, by separator: String) -> String {
        let characterSet = CharacterSet(charactersIn: characters)
        return components(separatedBy: characterSet).joined(separator: separator)
    }
}

Tried to come up with an appropriate function name according to Swift 3 naming convention.

Community
  • 1
  • 1
SoftDesigner
  • 5,640
  • 3
  • 58
  • 47
6

Less happened to me, I just want to change (a word or character) in the String

So I've use the Dictionary

  extension String{
    func replace(_ dictionary: [String: String]) -> String{
          var result = String()
          var i = -1
          for (of , with): (String, String)in dictionary{
              i += 1
              if i<1{
                  result = self.replacingOccurrences(of: of, with: with)
              }else{
                  result = result.replacingOccurrences(of: of, with: with)
              }
          }
        return result
     }
    }

usage

let mobile = "+1 (800) 444-9999"
let dictionary = ["+": "00", " ": "", "(": "", ")": "", "-": ""]
let mobileResult = mobile.replace(dictionary)
print(mobileResult) // 001800444999
amin
  • 481
  • 5
  • 13
4

Xcode 11 • Swift 5.1

The mutating method of StringProtocol replacingOccurrences can be implemented as follow:

extension RangeReplaceableCollection where Self: StringProtocol {
    mutating func replaceOccurrences<Target: StringProtocol, Replacement: StringProtocol>(of target: Target, with replacement: Replacement, options: String.CompareOptions = [], range searchRange: Range<String.Index>? = nil) {
        self = .init(replacingOccurrences(of: target, with: replacement, options: options, range: searchRange))
    }
}

var name = "This is my string"
name.replaceOccurrences(of: " ", with: "+")
print(name) // "This+is+my+string\n"
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
4
var str = "This is my string"
str = str.replacingOccurrences(of: " ", with: "+")
print(str)
Yash Gotecha
  • 144
  • 3
3

This is easy in swift 4.2. just use replacingOccurrences(of: " ", with: "_") for replace

var myStr = "This is my string"
let replaced = myStr.replacingOccurrences(of: " ", with: "_")
print(replaced)
Md Tariqul Islam
  • 2,736
  • 1
  • 20
  • 35
3

Since Swift 2, String does no longer conform to SequenceType. In other words, you can not iterate through a string with a for...in loop.

The simple and easy way is to convert String to Array to get the benefit of the index just like that:

let input = Array(str)

I remember when I tried to index into String without using any conversion. I was really frustrated that I couldn’t come up with or reach a desired result, and was about to give up. But I ended up creating my own workaround solution, and here is the full code of the extension:

extension String {
    subscript (_ index: Int) -> String {
    
        get {
             String(self[self.index(startIndex, offsetBy: index)])
        }
    
        set {
            remove(at: self.index(self.startIndex, offsetBy: index))
            insert(Character(newValue), at: self.index(self.startIndex, offsetBy: index))
        }
    }
}

Now that you can read and replace a single character from string using its index just like you originally wanted to:

var str = "cat"
for i in 0..<str.count {
 if str[i] == "c" {
   str[i] = "h"
 }
}

print(str)

It’s simple and useful way to use it and get through Swift’s String access model. Now that you’ll feel it’s smooth sailing next time when you can loop through the string just as it is, not casting it into Array.

Try it out, and see if it can help!

Elserafy
  • 51
  • 3
2

I've implemented this very simple func:

func convap (text : String) -> String {
    return text.stringByReplacingOccurrencesOfString("'", withString: "''")
}

So you can write:

let sqlQuery = "INSERT INTO myTable (Field1, Field2) VALUES ('\(convap(value1))','\(convap(value2)')
Sergey
  • 5
  • 3
Blasco73
  • 2,980
  • 2
  • 24
  • 30
1

I think Regex is the most flexible and solid way:

var str = "This is my string"
let regex = try! NSRegularExpression(pattern: " ", options: [])
let output = regex.stringByReplacingMatchesInString(
    str,
    options: [],
    range: NSRange(location: 0, length: str.characters.count),
    withTemplate: "+"
)
// output: "This+is+my+string"
duan
  • 8,515
  • 3
  • 48
  • 70
1

Swift extension:

extension String {

    func stringByReplacing(replaceStrings set: [String], with: String) -> String {
        var stringObject = self
        for string in set {
            stringObject = self.stringByReplacingOccurrencesOfString(string, withString: with)
        }
        return stringObject
    }

}

Go on and use it like let replacedString = yorString.stringByReplacing(replaceStrings: [" ","?","."], with: "+")

The speed of the function is something that i can hardly be proud of, but you can pass an array of String in one pass to make more than one replacement.

Juan Boero
  • 6,281
  • 1
  • 44
  • 62
1

Here is the example for Swift 3:

var stringToReplace = "This my string"
if let range = stringToReplace.range(of: "my") {
   stringToReplace?.replaceSubrange(range, with: "your")
} 
1

Here's an extension for an in-place occurrences replace method on String, that doesn't no an unnecessary copy and do everything in place:

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

(The method signature also mimics the signature of the built-in String.replacingOccurrences() method)

May be used in the following way:

var string = "this is a string"
string.replaceOccurrences(of: " ", with: "_")
print(string) // "this_is_a_string"
Stéphane Copin
  • 1,888
  • 18
  • 18
1

Swift 5.5

But this might work in earlier versions.

I'm frequently replacing because I want to replace "any whitespace or -" with a _ or something like that. This extension on string lets me do that.

extension String {
    func removingCharacters(_ characters:CharacterSet) -> Self {
        Self(self.unicodeScalars.filter {
            !characters.contains($0)
        })
    }
    func removingCharacters(in string:String) -> Self {
        Self(self.unicodeScalars.filter {
            !CharacterSet(charactersIn:string).contains($0)
        })
    }
    
    func replacingCharacters(_ characters:CharacterSet, with newChar:Character) -> Self {
        String(self.compactMap( {
            CharacterSet(charactersIn: "\($0.1)").isSubset(of: characters)
             ? newChar : $0.1
        }))
    }
    
    func replacingCharacters(in string:String, with newChar:Character) -> Self {
        String(self.compactMap( {
            CharacterSet(charactersIn: "\($0)").isSubset(of: CharacterSet(charactersIn:string))
             ? newChar : $0
        }))
    }
}

usage:

print("hello \n my name\t is Joe".removingCharacters(.whitespacesAndNewlines))
print("hello \n my name\t is Joe".removingCharacters(in: " \t\n"))

print("ban annan anann ana".replacingCharacters(.whitespacesAndNewlines, with: "_"))
print("ban-annan anann ana".replacingCharacters(in: " -", with: "_"))

Obviously for a single character the .replacingOccurrences(of: " ", with: "+") is better.

I have not done a performance comparison to the

let toArray = aString.components(separatedBy: characterSet)
let backToString = toArray.joined(separator: "+") 

style done in Ramis's extension. I'd be interested if someone does.

See also replacing emoji's: https://stackoverflow.com/a/63416058/5946596

carlynorama
  • 166
  • 7
1

Starting from iOS 16 We could use new method on RangeReplaceableCollection replace(_:with:maxReplacements:), that uses Regex as a parameter, where we can customize our request.

var myString = "This is my string"
myString.replace(" ", with: "+")

But don't forget to import RegexBuilder to enable this

Nazariy Vlizlo
  • 778
  • 7
  • 16
0

If you don't want to use the Objective-C NSString methods, you can just use split and join:

var string = "This is my string"
string = join("+", split(string, isSeparator: { $0 == " " }))

split(string, isSeparator: { $0 == " " }) returns an array of strings (["This", "is", "my", "string"]).

join joins these elements with a +, resulting in the desired output: "This+is+my+string".

Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
0

you can test this:

let newString = test.stringByReplacingOccurrencesOfString(" ", withString: "+", options: nil, range: nil)

Haya Hashmat
  • 137
  • 10