How to remove multiple spaces in Strings with Swift 2

headkit picture headkit · Oct 10, 2015 · Viewed 10.3k times · Source

Until Swift 2 I used this extension to remove multiple whitespaces:

func condenseWhitespace() -> String {
        let components = self.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).filter({!Swift.isEmpty($0)})
        return " ".join(components)
}

but with Swift 2 now I get the error

Cannot invoke 'isEmpty' with an argument list of type '(String)'

How could I now remove multiple spaces with Swift 2? Thnx!

Answer

Eric Aya picture Eric Aya · Oct 10, 2015

In Swift 2, join has become joinWithSeparator and you call it on the array.

In filter, isEmpty should be called on the current iteration item $0.

To replace whitespaces and newline characters with unique space characters as in your question:

extension String {
    func condenseWhitespace() -> String {
        let components = self.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
        return components.filter { !$0.isEmpty }.joinWithSeparator(" ")
    }
}

let result = "Hello  World.\nHello!".condenseWhitespace()  // "Hello World. Hello!"

Because your function does not take any parameter you could make it a property instead:

extension String {
    var condensedWhitespace: String {
        let components = self.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
        return components.filter { !$0.isEmpty }.joinWithSeparator(" ")
    }
}

let result = "Hello  World.\nHello!".condensedWhitespace  // "Hello World. Hello!"

In Swift 3 there's even more changes.

Function:

extension String {
    func condenseWhitespace() -> String {
        let components = self.components(separatedBy: NSCharacterSet.whitespacesAndNewlines)
        return components.filter { !$0.isEmpty }.joined(separator: " ")
    }
}

let result = "Hello  World.\nHello!".condenseWhitespace()

Property:

extension String {
    var condensedWhitespace: String {
        let components = self.components(separatedBy: NSCharacterSet.whitespacesAndNewlines)
        return components.filter { !$0.isEmpty }.joined(separator: " ")
    }
}

let result = "Hello  World.\nHello!".condensedWhitespace

In Swift 4.2 NSCharacterSet is now CharacterSet, and you can omit and use dot syntax:

extension String {
    func condenseWhitespace() -> String {
        let components = self.components(separatedBy: .whitespacesAndNewlines)
        return components.filter { !$0.isEmpty }.joined(separator: " ")
    }
}

let result = "Hello  World.\nHello!".condenseWhitespace()  // "Hello World. Hello!"