2

Let's say I have List(1,2,3,4,5) and I want to get List(3,5,7,9), that is, the sums of the element and the previous (1+2, 2+3,3+4,4+5)

I tried to do this by making two lists:

val list1 = List(1,2,3,4)
val list2 = (list1.tail ::: List(0))                   // 2,3,4,5,0
for (n0_ <- list1; n1th_ <- list2) yield (n0_ + n1_)

But that combines all the elements with each other like a cross product, and I only want to combine the elements pairwise. I'm new to functional programming and I thought I'd use map() but can't seem to do so.

sventechie
  • 1,859
  • 1
  • 22
  • 51

3 Answers3

12

List(1, 2, 3, 4, 5).sliding(2).map(_.sum).to[List] does the job.

Docs:

def sliding(size: Int): Iterator[Seq[A]] 

Groups elements in fixed size blocks by passing a "sliding window" over them (as opposed to partitioning them, as is done in grouped.)

Infinity
  • 3,431
  • 3
  • 25
  • 46
  • Awesome! I had no idea there was a builtin for that. It makes sense, of course. – sventechie Sep 24 '13 at 19:43
  • To make this work in my context I had to work around this bug with sliding(2).filter(_.size==2): http://stackoverflow.com/questions/7958712/inconsistent-behaviour-for-xs-slidingn-if-n-is-less-than-size – sventechie Sep 24 '13 at 20:48
2

You can combine the lists with zip and use map to add the pairs.

val list1 = List(1,2,3,4,5)
list1.zip(list1.tail).map(x => x._1 + x._2)

res0: List[Int] = List(3, 5, 7, 9)
Brian
  • 20,195
  • 6
  • 34
  • 55
  • This is much easier to understand coming from the imperative world, thanks! – sventechie Sep 24 '13 at 20:43
  • The "sliding" answer is better. You might want to change the selected answer. – Dave Griffith Sep 24 '13 at 23:54
  • Thanks, Brian & Dave. Yes, I changed to the sliding answer although it exposes a Scala misbehavior -- an even sliding window with an odd list length results in the final element being included rather than dropped. – sventechie Sep 25 '13 at 14:22
1

Personally I think using sliding as Infinity has is the clearest, but if you want to use a zip-based solution then you might want to use the zipped method:

( list1, list1.tail ).zipped map (_+_)

In addition to being arguably clearer than using zip, it is more efficient in that the intermediate data structure (the list of tuples) created by zip is not created with zipped. However, don't use it with infinite streams, or it will eat all of your memory.

AmigoNico
  • 6,652
  • 1
  • 35
  • 45