【问题标题】:Scala reverse stringScala反向字符串
【发布时间】:2011-12-03 18:20:43
【问题描述】:

我是 scala 的新手,我只是在编写一个简单的函数来反转给定的字符串:

def reverse(s: String) : String
  for(i <- s.length - 1 to 0) yield s(i)

yield 返回一个 scala.collection.immutable.IndexedSeq[Char],并且不能将其转换为 String。 (或者是别的什么?)

这个函数怎么写?

【问题讨论】:

    标签: scala


    【解决方案1】:
      def rev(s: String): String = {
        val str = s.toList
        def f(s: List[Char], acc: List[Char]): List[Char] = s match {
          case Nil => acc
          case x :: xs => f(xs, x :: acc)
        }
        f(str, Nil).mkString
      }
    

    【讨论】:

    • 欢迎来到stackoverflow。除了您提供的答案之外,请考虑提供一个简短说明,说明为什么以及如何解决此问题。
    【解决方案2】:

    以上所有答案都是正确的,这是我的看法:

    scala> val reverseString = (str: String) => str.foldLeft("")((accumulator, nextChar) => nextChar + accumulator)
    reverseString: String => java.lang.String = <function1>
    
    scala> reverseString.apply("qwerty")
    res0: java.lang.String = ytrewq
    

    【讨论】:

      【解决方案3】:

      这是一个简短的版本

      def reverse(s: String) = ("" /: s)((a, x) => x + a)
      

      编辑 : 甚至更短,我们有非常神秘的

      def reverse(s: String) = ("" /: s)(_.+:(_))
      

      但我不会真的推荐这个......

      【讨论】:

      • 嗨 Luigi,你能对你的代码做一个简短的解释吗?谢谢
      • 希望我能想到这个。 @Dzhu 它只是使用 foldLeft/: 只是该方法的简写名称),它采用初始值,然后将运算符应用于从左到右的序列的每个值。在这种情况下,序列是字符串,运算符只是将字符串的字符添加到结果中。
      • @Dzhu "" /: s 是中缀表示法的方法调用。由于方法 /:: 结束,因此调用在 s 上,参数为 ""。如果您在 Scala 文档中查找 String ,您将找不到它,因为它只是 Java 类,但您会发现 StringOps 字符串被隐式转换为,在这里您将找到 /: 方法。它被柯里化并接受第二个参数,即(此处)(String, Char) =&gt; String 类型的匿名函数。另见stackoverflow.com/q/7339618/770361stackoverflow.com/questions/2293592/…
      【解决方案4】:

      你也可以用递归的方式写这个(把这个扔进去只是为了好玩)

      def reverse(s: String): String = {
        if (s.isEmpty) ""
        else reverse(s.tail) + s.head
      }
      

      【讨论】:

      • 这不会被优化
      【解决方案5】:

      注意这里已经定义了函数:

      scala> val x = "scala is awesome"
      x: java.lang.String = scala is awesome
      
      scala> x.reverse
      res1: String = emosewa si alacs
      

      但如果你想自己做:

      def reverse(s: String) : String =
      (for(i <- s.length - 1 to 0 by -1) yield s(i)).mkString
      

      或(有时最好使用until,但在这种情况下可能不是)

      def reverse(s: String) : String =
      (for(i <- s.length until 0 by -1) yield s(i-1)).mkString
      

      另外,请注意,如果您使用反向计数(从大一到小一),您应该指定负步长,否则您将得到一个空集:

      scala> for(i <- x.length until 0) yield i
      res2: scala.collection.immutable.IndexedSeq[Int] = Vector()
      
      scala> for(i <- x.length until 0 by -1) yield i
      res3: scala.collection.immutable.IndexedSeq[Int] = Vector(16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
      

      【讨论】:

      • 感谢 om-nom-nom,我想自己实现它,这样我可以学习 :)
      【解决方案6】:

      如 om-nom-nom 所示,注意by -1(否则你并没有真正迭代,你的结果将是空的)。您可以使用的另一个技巧是collection.breakOut

      也可以像这样提供给for理解:

      def reverse(s: String): String  =
        (for(i <- s.length - 1 to 0 by -1) yield s(i))(collection.breakOut)
      
      reverse("foo")
      // String = oof
      

      使用breakOut 的好处是可以避免像mkString 解决方案那样创建中间结构。

      注意:breakOut 正在利用 CanBuildFrom 和构建器,它们是 scala 2.8.0 中引入的重新设计的集合库的基础的一部分

      【讨论】:

        猜你喜欢
        • 2021-03-15
        • 2012-08-24
        • 2010-09-06
        • 2016-09-15
        • 2014-11-16
        • 2016-05-09
        • 2015-05-10
        • 2012-07-27
        • 2014-07-10
        相关资源
        最近更新 更多