swiftnscharacterset

Remove all non-numeric characters from a string in swift


I have the need to parse some unknown data which should just be a numeric value, but may contain whitespace or other non-alphanumeric characters.

Is there a new way of doing this in Swift? All I can find online seems to be the old C way of doing things.

I am looking at stringByTrimmingCharactersInSet - as I am sure my inputs will only have whitespace/special characters at the start or end of the string. Are there any built in character sets I can use for this? Or do I need to create my own?

I was hoping there would be something like stringFromCharactersInSet() which would allow me to specify only valid characters to keep


Solution

  • I was hoping there would be something like stringFromCharactersInSet() which would allow me to specify only valid characters to keep.

    You can either use trimmingCharacters with the inverted character set to remove characters from the start or the end of the string. In Swift 3 and later:

    let result = string.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789.").inverted)
    

    Or, if you want to remove non-numeric characters anywhere in the string (not just the start or end), you can filter the characters, e.g. in Swift 4.2.1:

    let result = string.filter("0123456789.".contains)
    

    Or, if you want to remove characters from a CharacterSet from anywhere in the string, use:

    let result = String(string.unicodeScalars.filter(CharacterSet.whitespaces.inverted.contains))
    

    Or, if you want to only match valid strings of a certain format (e.g., ####.##), you could use regular expression. For example, using the newer regular expression literals (as discussed in WWDC 2022’s video Meet Swift Regex and Swift Regex: Beyond the basics), enclosing the regex with / characters:

    if let range = string.firstRange(of: /\d+(\.\d*)?/) {
        let result = string[range] // or `String(string[range])` if you need `String`
    }
    

    Or, using the old range(of:options:) with the .regularExpression option:

    if let range = string.range(of: #"\d+(\.\d*)?"#, options: .regularExpression) {
        let result = string[range] // or `String(string[range])` if you need `String`
    }
    

    The behavior of these different approaches differ slightly, so it just depends on precisely what you're trying to do. Include or exclude the decimal point if you want decimal numbers, or just integers. There are lots of ways to accomplish this.


    For older, Swift 2 syntax, see previous revision of this answer.