【问题标题】:Trim only trailing whitespace from end of string in Swift 3在 Swift 3 中仅从字符串末尾修剪尾随空格
【发布时间】:2017-05-24 17:27:36
【问题描述】:

在 Swift 中修剪字符串的每个示例都删除了前导和尾随空格,但是如何仅删除尾随空格?

例如,如果我有一个字符串:

"    example  "

我怎么能得到:

"    example"

我找到的每个解决方案都显示trimmingCharacters(in: CharacterSet.whitespaces),但我想保留前导空格。

RegEx 是一种可能性,或者可以导出一个范围来确定要删除的字符的索引,但我似乎找不到一个优雅的解决方案。

【问题讨论】:

标签: swift string swift3


【解决方案1】:

使用正则表达式:

let string = "    example  "
let trimmed = string.replacingOccurrences(of: "\\s+$", with: "", options: .regularExpression)
print(">" + trimmed + "<")
// >    example<

\s+ 匹配一个或多个空白字符,$ 匹配 字符串的结尾。

【讨论】:

  • 是的,这可能更好。不用说,我不知道,但这也需要Foundation。
  • 没有。当有更好的工作工具时,您不应该使用正则表达式:字符集。见the answer by Obliquely
  • @ChrisJF:它完成了这项工作,无需递归或创建中间字符串。
【解决方案2】:

在 Swift 4 和 Swift 5 中

此代码还将删除尾随的新行。 它基于 Character 结构的方法 .isWhitespace

var trailingSpacesTrimmed: String {
    var newString = self

    while newString.last?.isWhitespace == true {
        newString = String(newString.dropLast())
    }

    return newString
}

【讨论】:

【解决方案3】:

这个简短的 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
    }
}

【讨论】:

    【解决方案4】:

    在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 保护并强制解包可选,因为总会有匹配。我认为这更好,因为它显然是安全的,并且如果您更改正则表达式仍然是安全的。我没有考虑性能。

    【讨论】:

      【解决方案5】:

      方便的字符串扩展在 Swift 4 中

      extension String {
      
          func trimmingTrailingSpaces() -> String {
              var t = self
              while t.hasSuffix(" ") {
                t = "" + t.dropLast()
              }
              return t
          }
      
          mutating func trimmedTrailingSpaces() {
              self = self.trimmingTrailingSpaces()
          }
      
      }
      

      【讨论】:

        【解决方案6】:

        斯威夫特 4

        extension String {
            var trimmingTrailingSpaces: String {
                if let range = rangeOfCharacter(from: .whitespacesAndNewlines, options: [.anchored, .backwards]) {
                    return String(self[..<range.lowerBound]).trimmingTrailingSpaces
                }
                return self
            }
        }
        

        【讨论】:

          【解决方案7】:

          这有点 hacky :D

          let message = "    example  "
          var trimmed = ("s" + message).trimmingCharacters(in: .whitespacesAndNewlines)
          trimmed = trimmed.substring(from: trimmed.index(after: trimmed.startIndex))
          

          【讨论】:

            【解决方案8】:

            Demosthese 的answer 是解决该问题的有用方法,但不是特别有效。这是对他们答案的升级,改为扩展 StringProtocol,并利用 Substring 消除重复复制的需要。

            extension StringProtocol {
            
                @inline(__always)
                var trailingSpacesTrimmed: Self.SubSequence {
                    var view = self[...]
            
                    while view.last?.isWhitespace == true {
                        view = view.dropLast()
                    }
            
                    return view
                }
            }
            

            【讨论】:

              【解决方案9】:

              每次从末尾删除时无需创建新字符串。

              extension String {
              
                  func trimRight() -> String {
                      String(reversed().drop { $0.isWhitespace }.reversed())
                  }
              }
              

              这对集合进行操作,并且只将结果转换回字符串一次。

              【讨论】:

                【解决方案10】:

                没有正则表达式就没有直接的方法来实现。或者,您可以使用以下函数来实现您所需的结果:

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

                【讨论】:

                  【解决方案11】:

                  使用 Swift 4 和 5 的单线解决方案

                  作为 Swift 和 iOS 编程的初学者,我真的很喜欢 @demothese 的上面带有 while 循环的解决方案,因为它很容易理解。但是,示例代码似乎比必要的要长。以下使用基本相同的逻辑,但将其实现为单行 while 循环。

                  // Remove trailing spaces from myString
                  while myString.last == " " { myString = String(myString.dropLast()) }
                  

                  这也可以使用.isWhitespace 属性来编写,就像@demothese 的解决方案一样,如下所示:

                  while myString.last?.isWhitespace == true { myString = String(myString.dropLast()) }
                  

                  这样做的好处(或坏处,取决于您的观点)会删除所有类型的空格,不仅是空格,而且(根据 Apple 文档)还包括换行符,特别是以下字符:

                  • “\t”(U+0009 字符表)
                  • “” (U+0020 空格)
                  • U+2029 段落分隔符
                  • U+3000 表意空间

                  注意:尽管.isWhitespace 是一个布尔值,但它不能直接在while 循环中使用,因为它最终是可选的?,因为可选.last 属性的链接返回@ 987654330@ 如果字符串(或集合)为空。自nil != true 以来,== true 逻辑就解决了这个问题。

                  我很想得到一些反馈,尤其是。万一有人发现这种简单的单行方法有任何问题或缺点。

                  【讨论】:

                    【解决方案12】:

                    斯威夫特 5

                    extension String {
                    
                       func trimTrailingWhiteSpace() -> String {
                           guard self.last == " " else { return self }
                        
                           var tmp = self
                           repeat {
                               tmp = String(tmp.dropLast())
                           } while tmp.last == " "
                        
                           return tmp
                    }
                    

                    }

                    【讨论】:

                      猜你喜欢
                      • 2013-09-11
                      • 2021-09-16
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-01-21
                      • 2011-08-11
                      相关资源
                      最近更新 更多