【问题标题】:Trimming strings in Scala在 Scala 中修剪字符串
【发布时间】:2013-08-01 13:21:20
【问题描述】:

如何在Scala中修剪字符串的开始和结束字符

对于",hello""hello," 等输入,我需要"hello" 的输出。

Scala 中是否有任何内置方法可以做到这一点?

【问题讨论】:

    标签: string scala


    【解决方案1】:

    试试

    val str = "  foo  "
    str.trim
    

    看看the documentation。如果您也需要删除 , 字符,您可以尝试以下操作:

    str.stripPrefix(",").stripSuffix(",").trim
    

    清理字符串前端的另一种方法是

    val ignoreable = ", \t\r\n"
    str.dropWhile(c => ignorable.indexOf(c) >= 0)
    

    它也会处理像",,, ,,hello"这样的字符串

    为了更好地衡量,这里有一个小函数,它从左到右一次扫描字符串:

    def stripAll(s: String, bad: String): String = {
    
        @scala.annotation.tailrec def start(n: Int): String = 
            if (n == s.length) ""
            else if (bad.indexOf(s.charAt(n)) < 0) end(n, s.length)
            else start(1 + n)
    
        @scala.annotation.tailrec def end(a: Int, n: Int): String =
            if (n <= a) s.substring(a, n)
            else if (bad.indexOf(s.charAt(n - 1)) < 0) s.substring(a, n)
            else end(a, n - 1)
    
       start(0)
    }
    

    使用喜欢

    stripAll(stringToCleanUp, charactersToRemove)
    

    例如,

    stripAll("  , , , hello , ,,,, ", " ,") => "hello"
    

    【讨论】:

    • @Dirk: 你确定tailrec 魔法不能用一些简单的正则表达式代码替换吗?此外,ignorable contains c 可能被认为更具可读性。
    • @ErikAllik:我很确定,所有这些都可以通过正则表达式完成(至少在这种情况下)。此外:来自 Scheme,我实际上发现自己经常使用尾递归;我认为,这是一个习惯问题,而不是其他任何事情。 tailrec 注释会导致编译器给我一个错误,如果它不能将代码重写为普通循环。我发现这很有帮助,因为我倾向于使用尾递归和 Java VM 的限制,以便在(例如)函数调用中正确支持它们。
    • 顺便说一句,trim 并没有真正记录在提供的文档链接中。你需要一些扎实的 scala-literate 挖掘(或只是实验)才能得到它的作用。
    【解决方案2】:

    要修剪字符串中的开始和结束字符,请混合使用 drop 和 dropRight:

    scala> "你好,".drop(1).dropRight(1)

    res4: 字符串 = 你好

    drop 调用删除第一个字符,dropRight 删除最后一个字符。请注意,这不像 trim 那样“智能”。如果“hello”的开头没有任何多余的字符,则将其修剪为“ello”。如果您需要更复杂的东西,正则表达式替换可能就是答案。

    【讨论】:

    • "substring" 抛出 java.lang.StringIndexOutOfBoundsException 所以你在使用它之前需要 "if" - 不太像 Scala
    • @CC 感谢您的建设性批评。我同意使用“if”很笨拙,并更新了我的答案以用 drop() 替换子字符串,这应该可以完成同样的事情而不会出现异常
    • 当您有固定长度的左右修剪时,这非常简单。
    • 这仅适用于要删除的固定数量的字符,并且依赖于开头和结尾都需要修剪的事实。这种情况很少见。
    • 也许吧,但 OP 专门询问“如何修剪字符串的开始和结束字符”,而不是一般的字符串修剪实用程序。
    【解决方案3】:

    如果您只想修剪逗号并且两端可能有多个逗号,您可以这样做:

    str.dropWhile(_ == ',').reverse.dropWhile(_ == ',').reverse
    

    这里使用reverse是因为没有dropRightWhile

    如果您正在查看单个可能的逗号,stripPrefixstripSuffix 是最好的选择,正如 Dirk 所指出的那样。

    【讨论】:

      【解决方案4】:

      假设您只想从给定字符串的 前缀后缀 中去除无效字符(不扫描整个字符串),这里有一个很小的trimPrefixSuffixChars 函数可以快速执行所需的效果:

      def trimPrefixSuffixChars(
          string: String
        , invalidCharsFunction: (Char) => Boolean = (c) => c == ' '
      ): String =
        if (string.nonEmpty)
          string
            .dropWhile(char => invalidCharsFunction(char))  //trim prefix
            .reverse
            .dropWhile(char => invalidCharsFunction(char)) //trim suffix
            .reverse
        else
          string
      

      此函数为invalidCharsFunction 提供默认值,仅将空格 (" ") 字符定义为无效。以下是以下输入字符串的转换结果:

      trimPrefixSuffixChars(" Tx  ")     //returns "Tx"
      trimPrefixSuffixChars(" . Tx . ")  //returns ". Tx ."
      trimPrefixSuffixChars(" T x  ")    //returns "T x"
      trimPrefixSuffixChars(" . T x . ") //returns ". T x ."
      

      如果你愿意指定你自己的invalidCharsFunction 函数,然后像这样在调用中传递它:

      trimPrefixSuffixChars(",Tx. ", (c) => !c.isLetterOrDigit)     //returns "Tx"
      trimPrefixSuffixChars(" ! Tx # ", (c) => !c.isLetterOrDigit)  //returns "Tx"
      trimPrefixSuffixChars(",T x. ", (c) => !c.isLetterOrDigit)    //returns "T x"
      trimPrefixSuffixChars(" ! T x # ", (c) => !c.isLetterOrDigit) //returns "T x"
      

      这试图简化其他答案中提供的一些示例解决方案。

      【讨论】:

        【解决方案5】:

        有人请求了一个正则表达式版本,应该是这样的:

        val result = " , ,, hello, ,,".replaceAll("""[,\s]+(|.*[^,\s])[,\s]+""", "'$1'")
        

        结果是:result: String = hello

        正则表达式的缺点(不仅在这种情况下,而且总是如此)是对于尚未熟悉语法的人来说很难阅读。不过,代码简洁明了。

        【讨论】:

        • 这个正则表达式也可以简化为" , ,, hello, ,,".replaceAll("""[,\s]+""", "")
        • @Grafluxe,这也会从字符串的中间删除,这与问题所要求的有所不同。
        • 嗨,Pianosaurus,我的逻辑返回和你的一样。随意在您的 REPL 中尝试一下。 val result = " , ,, hello, ,,".replaceAll("""[,\s]+""", "") 输出 result: String = hello ```
        • @Grafluxe:只是因为那个特定的字符串在末尾有要删除的字符,而不是在中间。查看",he,llo,".replaceAll("""[,\s]+""", "")",he,llo,".replaceAll("""[,\s]+(|.*[^,\s])[,\s]+""", "'$1'") 之间的区别。
        • 虽然我从我的答案中删除了垃圾,并改用replaceAll 写了它。
        猜你喜欢
        • 1970-01-01
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多