Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Scala, how do I fold a List and return the intermediate results?

Tags:

scala

I've got a List of days in the month:

val days = List(31, 28, 31, ...)

I need to return a List with the cumulative sum of days:

val cumDays = List(31, 59, 90)

I've thought of using the fold operator:

(0 /: days)(_ + _)

but this will only return the final result (365), whereas I need the list of intermediate results.

Anyway I can do that elegantly?

like image 970
lindelof Avatar asked Jul 11 '10 22:07

lindelof


People also ask

How does fold work in Scala?

The fold method takes two sets of arguments. One contains a start value and the other a combining function. It then steps through the list, recursively applying the function to two operands: an accumulated value and the next element in the list. In the first step, the start value, 0, acts as the first operand.

How does fold left work in Scala?

foldLeft() method is a member of TraversableOnce trait, it is used to collapse elements of collections. It navigates elements from Left to Right order. It is primarily used in recursive functions and prevents stack overflow exceptions.


3 Answers

Scala 2.8 has the methods scanLeft and scanRight which do exactly that.

For 2.7 you can define your own scanLeft like this:

def scanLeft[a,b](xs:Iterable[a])(s:b)(f : (b,a) => b) =
  xs.foldLeft(List(s))( (acc,x) => f(acc(0), x) :: acc).reverse

And then use it like this:

scala> scanLeft(List(1,2,3))(0)(_+_)
res1: List[Int] = List(0, 1, 3, 6)
like image 81
sepp2k Avatar answered Oct 09 '22 23:10

sepp2k


I'm not sure why everybody seems to insist on using some kind of folding, while you basically want to map the values to the cumulated values...

val daysInMonths = List(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)

val cumulated = daysInMonths.map{var s = 0; d => {s += d; s}}

//--> List[Int] = List(31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
like image 21
Landei Avatar answered Oct 10 '22 01:10

Landei


You can simply perform it:

daysInMonths.foldLeft((0, List[Int]()))
                     {(acu,i)=>(i+acu._1, i+acu._1 :: acu._2)}._2.reverse
like image 6
mucar Avatar answered Oct 10 '22 00:10

mucar