Reputation: 4381
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 ?
Upvotes: 15
Views: 37379
Reputation: 163447
Another variation using tail recursion, using an inner function taking the first char of the remaining and prepending it to the accumulator.
import scala.annotation.tailrec
def reverse(s: String): String = {
@tailrec
def revTailRec(remaining: String, acc: String): String = {
if (remaining.headOption.nonEmpty) revTailRec(remaining.tail, remaining.head + acc)
else acc
}
revTailRec(s, "")
}
reverse("foobar") // raboof
Upvotes: 0
Reputation: 1
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
Upvotes: 0
Reputation: 11
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
}
Upvotes: 0
Reputation: 2144
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
Upvotes: 4
Reputation: 51109
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...
Upvotes: 12
Reputation: 2597
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
}
Upvotes: 9
Reputation: 62835
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)
Upvotes: 29
Reputation: 41646
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
Upvotes: 8