Scala反转字符串

14

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

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

yield返回一个scala.collection.immutable.IndexedSeq[Char]类型的数据,不能直接转换为字符串(或者是其他类型?)

我该如何编写这个函数?

7个回答

28
请注意,已经有一个定义好的函数:
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,我想自己实现它以便我可以学习 :) - Dzhu

12

这是一个简短的版本

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

编辑:或者更简单地说,我们有非常神秘的东西。

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

但我实际上不建议这样做...


2
嗨,Luigi,你可以为你的代码提供一个简短的解释吗?谢谢。 - Dzhu
1
希望我能想到这个。@Dzhu,它只是使用了foldLeft/:只是该方法的简写名称),它接受一个初始值,然后从左到右对序列的每个值应用运算符。在这种情况下,序列是字符串,运算符只是将字符串的字符前置到结果中。 - Thomas Lockney
1
@Dzhu "" /: s 是一种中缀符号的方法调用。由于方法 /:: 结尾,因此调用是在 s 上进行的,并带有参数 ""。如果您在 Scala 文档中查找 String,您将找不到它,因为它只是 Java 类,但您会发现 Strings 隐式转换为 StringOps,并且在这里您将找到 /: 方法。它是柯里化的,并且需要第二个参数,这里是一个类型为 (String, Char) => String 的匿名函数。另请参见 https://dev59.com/VWs05IYBdhLWcg3wR_22,https://dev59.com/fHE95IYBdhLWcg3wft1w#2303291 - Luigi Plinge

9
你也可以使用递归方法来编写这个程序(仅供娱乐)
def reverse(s: String): String = {
  if (s.isEmpty) ""
  else reverse(s.tail) + s.head
}

2
这不会被优化。 - gurghet

8

根据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引入的重新设计的集合库的基础。

4
所有上述答案都是正确的,这是我的观点:
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

0
这是我反转字符串的版本。
scala> val sentence = "apple"
sentence: String = apple

scala> sentence.map(x => x.toString).reduce((x, y) => (y + x))
res9: String = elppa

0
  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
  }

3
欢迎来到stackoverflow。除了您提供的答案外,请考虑提供一些简要说明,说明为什么以及如何解决这个问题。 - jtate

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