如何使用Swift 2移除字符串中的多个空格

30

直到Swift 2,我使用这个扩展名来删除多个空格:

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

但是使用 Swift 2 现在我收到了错误消息

无法调用类型为 '(String)' 的参数列表的 'isEmpty'

如何使用 Swift 2 删除多个空格? 谢谢!

8个回答

59
在Swift 2中,`join`变成了`joinWithSeparator`,并且需要对数组调用该方法。 在`filter`中,应该在当前迭代项`$0`上调用`isEmpty`。 要将空格和换行符替换为问题中的唯一空格字符:
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!"
因为你的函数不需要任何参数,所以你可以将它改为属性:
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!"

Swift 3 中有更多的变化。

函数:

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()

属性:

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

Swift 4.2中,NSCharacterSet现在更名为CharacterSet,并且您可以省略并使用点语法:

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!"

小心,如果你想让它与空格和换行符一起工作,你需要将新行视为新行而不是“ ”当你连接时。func condenseWhitespace() -> String { let components = self.components(separatedBy: .whitespaces) let tmpstr = components.filter { !$0.isEmpty }.joined(separator: " ") let components2 = tmpstr.components(separatedBy: .newlines) return components2.filter { !$0.isEmpty }.joined(separator: "\n") } - Climbatize
1
这个扩展在Swift 5中运行得非常好。救命代码!谢谢 :) - sugarakis

29

将字符串分割成数组,然后再次连接在“非内存有效”的情况下。这需要大量的内存。在这种情况下最好的方法是扫描给定的字符串并对其执行操作。正则表达式是扫描文本的高级方式。给出以下解决方案以得出上述结论:

Swift 4.x

extension String {

    func removeExtraSpaces() -> String {
        return self.replacingOccurrences(of: "[\\s\n]+", with: " ", options: .regularExpression, range: nil)
    }

}

用途

let startingString = "hello   world! \n\n I am   here!"
let processedString = startingString.removeExtraSpaces()
print(processedString)

输出:

processedString => "你好世界!我在这里!"

根据自己的需求,您可以做更多的事情,但我在这里指出的是要使用字符串正则表达式,而不是创建数组,否则会消耗大量内存。


谢谢!这比创建不必要的数组要好。 - ozd
@JeanNicolas,你可以通过将.trimmingCharacters(in: .whitespacesAndNewlines)函数添加到你的扩展中来实现。上述解决方案将多个空格或换行符减少为一个空格。如果你能让这个功能更加负责地修剪字符串,我会非常感激。谢谢 :-) - Gurjit Singh

13

最清晰的版本。文档齐全,内存占用少,极易使用。

extension String {

    /// Returns a condensed string, with no extra whitespaces and no new lines.
    var condensed: String {
        return replacingOccurrences(of: "[\\s\n]+", with: " ", options: .regularExpression, range: nil)
    }

    /// Returns a condensed string, with no whitespaces at all and no new lines.
    var extraCondensed: String {
        return replacingOccurrences(of: "[\\s\n]+", with: "", options: .regularExpression, range: nil)
    }

}

使用方法:

let a = " Hello\n  I am  a string  ".condensed
let b = " Hello\n  I am  a string  ".extraCondensed

输出:

a: "你好,我是一个字符串"

b: "HelloIamastring"


8

SWIFT 3:更简洁的版本

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

使用var相比func有什么优势? - asdf
1
我不认为这会有任何不同。只是帮你省点事(). - Yaroslav Dukal

1
这里是我的:它实际上是如何工作的。
extension String {

    func removeExtraSpaces() -> String {
        var data  = ""
        var numberOfSpace = 0
        let items = self.getComponents(separatedBy: " ")
        for item in items{
            if item == " "{
                numberOfSpace = numberOfSpace + 1
            }else{
                numberOfSpace = 0
            }
            if numberOfSpace == 1 || numberOfSpace == 0 {
                data =  data + item
                //data.append(item)
            }
        }
        return data
    }
} 

使用方法

 var message = "What  is the    purpose   of life?"
 message = message.removeExtraSpaces()
 print(message)

输出:

生命的目的是什么?


1
以下代码对我有效。我需要从字符串中删除额外的空格。
var example = "    Hello       world   "

func removeSpacers(from word: String) -> String {
var finalResult = ""
var spacesCount = 0

let trimmed = word.trimmingCharacters(in: .whitespaces)
let components = trimmed.components(separatedBy: " ")

// if we have not any spaces we returning trimmed string
guard components.contains(where: { $0 == "" }) else { return trimmed }
components.forEach {
    // because .components returning ""(empty string)
    if $0 == "" {
        spacesCount += 1
    } else {
        // if another element not space, we could add space(the space between words)
        if spacesCount != 0 {
            spacesCount = 0
            finalResult.append(" ")
        }
    }
    // so if we have no spaces we could add word no result string
    if spacesCount == 0 {
        finalResult.append($0)
    }
}
return finalResult

}

我做了几个测试,它们都成功了。
 func testRemoveSpaceFromStringWithSpacesOnCenter() {
    // given
    let string = "Hello     world"

    // when
    let result = pfromatter.removeSpaces(from: string)

    // then
    let expected = "Hello world"
    XCTAssertEqual(expected, result)
}

func testRemoveSpaceFromStringWithSpacesOnSide() {
    // given
    let string = " Hello world "

    // when
    let result = pfromatter.removeSpaces(from: string)

    // then
    let expected = "Hello world"
    XCTAssertEqual(expected, result)
}

0
var str = "Hello  World.\nHello!"

if let regex = try? NSRegularExpression(pattern: "\\s+", options:NSRegularExpression.Options.caseInsensitive)
{
    str = regex.stringByReplacingMatches(in: str, options: [], range: NSMakeRange(0, str.count), withTemplate: " ")

}

0
如果你想一次性去除重复的空格和任何前导/尾随的空格,你可以使用下面的解决方案:
extension String {
    func trimmingExtraWhitespace() -> String {
        return self.replacingOccurrences(of: "(?<=\\s)\\s+|\\s+(?=$)|(?<=^)\\s+", 
                                         with: "", 
                                         options: .regularExpression)
    }
}

它的功能是:
  • (?<=\\s)\\s+ 匹配所有在空格之前的空白字符
  • \\s+(?=$) 匹配所有在字符串末尾的空白字符
  • (?<=^)\\s+ 匹配所有在字符串开头的空白字符
备注:
  • 正则表达式中的 \s 包括空格、制表符和换行符,所以不需要显式指定 \n
  • 在 Swift 中需要转义 \s,因此使用双反斜杠 \\
示例:
var originalString = "  Hello   world  "
var processedString = originalString.trimmingExtraWhitespace()
print("Original: \(originalString)")
print("Processed: \(processedString)")

输出:

Original:   Hello   world  
Processed: Hello world

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接