在 Swift 中修剪字符串的每个示例都会删除前导和尾随空格,但是如何仅删除尾随空格?
例如,如果我有一个字符串:
" example "
我该如何最终得到:
" example"
我找到的每个解决方案都使用 trimmingCharacters(in: CharacterSet.whitespaces)
,但是我想保留前导空格。
正则表达式是一种可能性,或者可以派生出一个范围来确定要删除的字符的索引,但我似乎找不到一个优雅的解决方案。
在 Swift 中修剪字符串的每个示例都会删除前导和尾随空格,但是如何仅删除尾随空格?
例如,如果我有一个字符串:
" example "
我该如何最终得到:
" example"
我找到的每个解决方案都使用 trimmingCharacters(in: CharacterSet.whitespaces)
,但是我想保留前导空格。
正则表达式是一种可能性,或者可以派生出一个范围来确定要删除的字符的索引,但我似乎找不到一个优雅的解决方案。
通过正则表达式:
let string = " example "
let trimmed = string.replacingOccurrences(of: "\\s+$", with: "", options: .regularExpression)
print(">" + trimmed + "<")
// > example<
\s+
匹配一个或多个空白字符,$
匹配字符串的结尾。
Foundation
。 - Raphael在 Swift 4 和 Swift 5 中
这段代码还会移除末尾的空行。它基于 Character
结构体的方法 .isWhitespace
运作。
var trailingSpacesTrimmed: String {
var newString = self
while newString.last?.isWhitespace == true {
newString = String(newString.dropLast())
}
return newString
}
这个短小的 Swift 3 字符串扩展使用 rangeOfCharacter
的.anchored
和.backwards
选项,如果需要循环,它会递归调用自身。由于编译器期望参数为一个CharacterSet,因此在调用时可以直接提供静态值,例如 "1234 ".trailing(.whitespaces)
将返回 "1234"
。(我没有进行计时,但预计比正则表达式更快。)
extension String {
func trailingTrim(_ characterSet : CharacterSet) -> String {
if let range = rangeOfCharacter(from: characterSet, options: [.anchored, .backwards]) {
return self.substring(to: range.lowerBound).trailingTrim(characterSet)
}
return self
}
}
Demosthese的答案是一个有用的解决方案,但并不特别高效。这是对他们答案的升级,扩展了StringProtocol
,利用Substring
来消除重复复制的需要。
extension StringProtocol {
@inline(__always)
var trailingSpacesTrimmed: Self.SubSequence {
var view = self[...]
while view.last?.isWhitespace == true {
view = view.dropLast()
}
return view
}
}
Foundation
中,您可以获取与正则表达式匹配的索引范围。您还可以替换子范围。将它们结合起来,我们得到:import Foundation
extension String {
func trimTrailingWhitespace() -> String {
if let trailingWs = self.range(of: "\\s+$", options: .regularExpression) {
return self.replacingCharacters(in: trailingWs, with: "")
} else {
return self
}
}
}
import Foundation
extension String {
mutating func trimTrailingWhitespace() {
if let trailingWs = self.range(of: "\\s+$", options: .regularExpression) {
self.replaceSubrange(trailingWs, with: "")
}
}
}
\s*
(就像 Martin R. 一开始做的那样),我们可以跳过 if let
守卫并强制解包可选项,因为总会有一个匹配。我认为这更好,因为它显然是安全的,并且如果您更改正则表达式,它仍然是安全的。我没有考虑性能。方便的字符串扩展 在 Swift 4 中
extension String {
func trimmingTrailingSpaces() -> String {
var t = self
while t.hasSuffix(" ") {
t = "" + t.dropLast()
}
return t
}
mutating func trimmedTrailingSpaces() {
self = self.trimmingTrailingSpaces()
}
}
Swift 4
extension String {
var trimmingTrailingSpaces: String {
if let range = rangeOfCharacter(from: .whitespacesAndNewlines, options: [.anchored, .backwards]) {
return String(self[..<range.lowerBound]).trimmingTrailingSpaces
}
return self
}
}
extension String {
func trimRight() -> String {
String(reversed().drop { $0.isWhitespace }.reversed())
}
}
这个操作针对集合进行,只有在操作结束后才将结果转换回字符串。
这有点“hacky”(即不太正规) :D
let message = " example "
var trimmed = ("s" + message).trimmingCharacters(in: .whitespacesAndNewlines)
trimmed = trimmed.substring(from: trimmed.index(after: trimmed.startIndex))
如果没有正则表达式,就没有直接的方法来实现这一点。或者,您可以使用下面的函数来实现所需的结果:
func removeTrailingSpaces(with spaces : String) -> String{
var spaceCount = 0
for characters in spaces.characters{
if characters == " "{
print("Space Encountered")
spaceCount = spaceCount + 1
}else{
break;
}
}
var finalString = ""
let duplicateString = spaces.replacingOccurrences(of: " ", with: "")
while spaceCount != 0 {
finalString = finalString + " "
spaceCount = spaceCount - 1
}
return (finalString + duplicateString)
}
let str = " Himanshu "
print(removeTrailingSpaces(with : str))