Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala partial sum with current and all past elements in the list

Tags:

arrays

scala

sum

We have a list of integers like: [1,4,5,6,6,7,9].

The idea is to generate a list with the same length and sums up till the current element like: [1,5,10,16,22,29,38].

In the Java world it would look like:

int sum = 0;
int[] table = {1,4,5,6,6,7,9}
int[] res = new int[table.length]
for(int i=0; i<table.length; i++) {
  sum += table[i]
  res[i] = sum
}

I know there exist more elegant and efficient solutions. My question is how to do something like this in Scala in more fuctional way?

Thx!

like image 228
zmeda Avatar asked Mar 24 '15 07:03

zmeda


2 Answers

You are looking for the scan combinator.

List(1,4,5,6,6,7,9).scanLeft(0)(_ + _)
res1: List[Int] = List(0, 1, 5, 10, 16, 22, 29, 38)

Remove the leading element with tail if you want I am not aware of a version of scan that does not take an initial value. The complexity is O(n) for this guy and you could implement it yourself with folding the list via an accumulator and a list (that contains past accumulators). The latter you take as a result.

like image 197
uberwach Avatar answered Oct 15 '22 14:10

uberwach


@uberwatch's answer is the right one, but for the sake of completeness, here's the more "generic" functional solution using foldLeft:

val xs = Vector(1,4,5,6,6,7,9)
val (sumList, sum) = 
  xs.foldLeft((Vector.empty[Int], 0)) {
    case ((list, total), x) => 
      val newTotal = x + total
      (list :+ newTotal, newTotal) 
  }
// sumList: Vector(1, 5, 10, 16, 22, 29, 38)
// sum: Int = 38
like image 31
dhg Avatar answered Oct 15 '22 13:10

dhg