14

I'm a newbie to scala, I'm just writing a simple function to reverse a given string:

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

the yield gives back a scala.collection.immutable.IndexedSeq[Char], and can not convert it to a String. (or is it something else?)

how do i write this function ?

Dzhu
  • 4,311
  • 5
  • 36
  • 48

7 Answers7

28

Note that there is already defined function:

scala> val x = "scala is awesome"
x: java.lang.String = scala is awesome

scala> x.reverse
res1: String = emosewa si alacs

But if you want to do that by yourself:

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

or (sometimes it is better to use until, but probably not in that case)

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

Also, note that if you use reversed counting (from bigger one to less one value) you should specify negative step or you will get an empty set:

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
  • 62,329
  • 13
  • 183
  • 228
12

Here's a short version

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

edit : or even shorter, we have the fantastically cryptic

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

but I wouldn't really recommend this...

Luigi Plinge
  • 50,650
  • 20
  • 113
  • 180
  • 2
    Hi Luigi, can you give a short explanation for your code? thanks – Dzhu Oct 09 '11 at 21:19
  • 1
    Wish I had thought of this one. @Dzhu it's just using a `foldLeft` (`/:` is just a short-hand name for that method) which takes an initial value and then applies an operator to each value of a sequence from left to right. In this case, the sequence is the string and the operator is just prepending the characters of the string to the result. – Thomas Lockney Oct 09 '11 at 22:00
  • 1
    @Dzhu `"" /: s` is a method call in infix notation. The call is on `s` with argument `""` since the method `/:` ends in `:`. If you look up String in the Scala docs you won't find it since it's just the Java class, but you will find `StringOps` to which Strings are implicitly converted, and here you'll find the `/:` method. It is curried and takes a second argument, which is (here) an anonymous function of type `(String, Char) => String`. See also http://stackoverflow.com/q/7339618/770361, http://stackoverflow.com/questions/2293592/functional-programming-scala-map-and-fold-left/2303291#2303291 – Luigi Plinge Oct 09 '11 at 22:48
9

You could also write this using a recursive approach (throwing this one in just for fun)

def reverse(s: String): String = {
  if (s.isEmpty) ""
  else reverse(s.tail) + s.head
}
Thomas Lockney
  • 2,567
  • 20
  • 13
8

As indicated by om-nom-nom, pay attention to the by -1 (otherwise you are not really iterating and your result will be empty). The other trick you can use is collection.breakOut.

It can also be provided to the for comprehension like this:

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

reverse("foo")
// String = oof

The benefit of using breakOut is that it will avoid creating a intermediate structure as in the mkString solution.

note: breakOut is leveraging CanBuildFrom and builders which are part of the foundation of the redesigned collection library introduced in scala 2.8.0

Community
  • 1
  • 1
huynhjl
  • 41,520
  • 14
  • 105
  • 158
4

All the above answers are correct and here's my take:

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
Sudheer Aedama
  • 2,116
  • 2
  • 21
  • 39
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
    Welcome to stackoverflow. In addition to the answer you've provided, please consider providing a brief explanation of why and how this fixes the issue. – jtate Oct 15 '19 at 21:47
0

Here is my version of reversing a string.

scala> val sentence = "apple"
sentence: String = apple

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