Friday, September 18, 2009

A quick sample of Lists and Tuples in Scala

So I've been challenged with a simple problem to solve in Scala, that is; to take a List of values and and then sum each corresponding value in the list together into a resultant list.

For example:

[1,2,3,4,5] becomes [3,5,7,9]

You can accomplish this in Scala using the List class and its functions, these include:
  • zip : this function takes an input list and creates a list of tuples with each mapping pair, discarding jagged values.
  • tail : this function returns a list minus the first element of the list on which tail is performed.
  • foldLeft : combines the elements of the list together with a seed value (in my case I use a target List).
  • reverse : reverses the order of the list.
so here is the code to do this:
object SumPairs extends Application {

val numbers = List(1,2,3,4,5);
val result =
.foldLeft(List[Int]()) (
(list, y) => {
y._1 + y._2 :: list


Basically this works as follows:
  1. I create a List of Tuples of each adjacent value in the List by getting the tail of the List.
  2. I get each Tuple in the list, sum it and prepend it to the List returned by "foldLeft".
  3. I reverse the List to fix the order as a result of doing a prepend.
Now this is is designed to be functional but not overly complex (at least I hope not), Since I'm still fairly green in the Scala dark arts I'd like to hear on improvements.

BTW the challenge I'm talking about can be found here.


Another solution would be to use List.flatMap which basically takes a function which returns an Iterable and appends it to a function, it pretty similar, It's maybe a little more concise, I'll let you decide:

val numbers = List(1,2,3,4,5); {
value => {


Eastsun said...

scala> val nums = 1::2::3::4::5::Nil
nums: List[Int] = List(1, 2, 3, 4, 5)

scala>{ case(x,y) => x+y }
res0: List[Int] = List(3, 5, 7, 9)


Keep running said...

scala> val nums = List.range(1,6)
nums: List[Int] = List(1, 2, 3, 4, 5)

scala> for((x,y) <- nums zip nums.tail) yield x+y
res0: List[Int] = List(3, 5, 7, 9)

วีรศักดิ์ ดุงศรีแก้ว said...

Or just map {
case (a,b) => a + b

Tony Morris said...

Use foldRight instead of foldLeft+reverse. Note that reverse is a specialisation of foldLeft and that any foldRight can be written using 2 foldLefts.

foldRight really shines when used across a lazy data structure (though scala.Stream's foldRight is broken).