Skip to content

Instantly share code, notes, and snippets.

@joshavant
Created May 1, 2016 00:19
Show Gist options
  • Save joshavant/d9a94373ec45a7b5d7e7d98263e46e1e to your computer and use it in GitHub Desktop.
Save joshavant/d9a94373ec45a7b5d7e7d98263e46e1e to your computer and use it in GitHub Desktop.
Replace characters from set with replacement string
import Foundation
extension String {
func replaceCharactersFromSet(characterSet: NSCharacterSet, replacementString: String) -> String {
let scanner = NSScanner(string: self)
scanner.charactersToBeSkipped = nil
let sanitizedString = NSMutableString(capacity: self.characters.count)
while(!scanner.atEnd) {
var buffer: NSString? = ""
if scanner.scanUpToCharactersFromSet(characterSet, intoString: &buffer), let buffer = buffer {
sanitizedString.appendString(buffer as String)
} else {
scanner.scanLocation = scanner.scanLocation + 1
sanitizedString.appendString(replacementString as String)
}
}
return sanitizedString as String
}
}
@AliSoftware
Copy link

AliSoftware commented May 1, 2016

Why not simply this?

import Foundation

extension String {
  func replaceCharactersFromSet(characterSet: NSCharacterSet, replacementString: String = "") -> String {
    return self.componentsSeparatedByCharactersInSet(characterSet).joinWithSeparator(replacementString)
  }
}

Which gives:

"Hello, world!".replaceCharactersFromSet(NSCharacterSet.letterCharacterSet().invertedSet, replacementString: "_")
// "Hello__world_"
"Hello world this is Swift".replaceCharactersFromSet(.whitespaceCharacterSet())
// "HelloworldthisisSwift"

@AliSoftware
Copy link

AliSoftware commented May 1, 2016

Also your code have a bug with strings containing chars needing more than one utf16 word to represent them (which is the case for some emoji especially):

let wine_cool = "\u{1f377} makes me \u{1f60e}" // (can't paste the :wine: and :sunglasses: emojis in code (GitHub refuse with an error), so let's use their code point instead)
wine_cool.replaceCharactersFromSet(NSCharacterSet.letterCharacterSet().invertedSet, replacementString: "_")
// my code returns: "__makes_me__"
// while your code returns: "_� makes_me__�"

@joshavant
Copy link
Author

Ah! I've needed to learn more about Unicode formats, so this was especially helpful and much appreciated. Thank you!

@KevinLaRosa
Copy link

extension String {
    func replaceCharactersFromSet(characterSet: CharacterSet, replacementString: String) -> String {
        let scanner = Scanner(string: self)
        scanner.charactersToBeSkipped = nil
        
        let sanitizedString = NSMutableString(capacity: self.count)
        
        while(!scanner.isAtEnd) {
            var buffer: NSString? = ""
            if scanner.scanUpToCharacters(from: characterSet as CharacterSet, into: &buffer), let buffer = buffer {
                sanitizedString.append(buffer as String)
            } else {
                scanner.scanLocation = scanner.scanLocation + 1
                sanitizedString.append(replacementString as String)
            }
        }
        
        return sanitizedString as String
    }
}

@MihaelIsaev
Copy link

@AliSoftware answer but in Swift 4/5

extension String {
    func replaceCharactersFromSet(characterSet: CharacterSet, replacementString: String = "") -> String {
        return components(separatedBy: characterSet).joined(separator: replacementString)
    }
}

@SerggioC
Copy link

SerggioC commented Jun 2, 2020

👍

@alexwal
Copy link

alexwal commented Aug 6, 2023

Useful, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment