Source: https://alvinalexander.com/scala/how-to-walk-scala-collections-reduceleft-foldright-cookbook
This is an excerpt from theScala Cookbook(partially modified for the internet). This is Recipe 10.20, “How to Walk Through a Scala Collection with the_reduce_and_fold_Methods”
Problem
You want to walk through all of the elements in a Scala sequence, comparing two neighboring elements as you walk through the collection.
Solution
Use thereduceLeft
,foldLeft
,reduceRight
, andfoldRight
methods to walk through the elements in a sequence, applying your function to neighboring elements to yield a new result, which is then compared to the next element in the sequence to yield a new result.
Related methods, such as
scanLeft
andscanRight
, are also shown in the Discussion.
For example, usereduceLeft
to walk through a sequence from left to right (from the first element to the last).reduceLeft
starts by comparing the first two elements in the collection with your algorithm, and returns a result. That result is compared with the third element, and that comparison yields a new result. That result is compared to the fourth element to yield a new result, and so on.
Given that sequence, usereduceLeft
to determine different properties about the collection. The following example shows how to get the sum of all the elements in the sequence:
scala
>
a.reduceLeft(_ + _)
res0: Int = 64
The following examples show how to usereduceLeft
to get the product of all elements in the sequence, the smallest value in the sequence, and the largest value:
>
a.reduceLeft(_ * _)
res1: Int = 388800
scala
>
a.reduceLeft(_ min _)
res2: Int = 2
scala
>
a.reduceLeft(_ max _)
res3: Int = 20
foldLeft, reduceRight, and foldRight
ThefoldLeft
method works just likereduceLeft
, but it lets you set a seed value to be used for the first element. The following examples demonstrate a “sum” algorithm, first withreduceLeft
and then withfoldLeft
, to demonstrate the difference:
scala
>
val a = Array(1, 2, 3)
a: Array[Int] = Array(1, 2, 3)
scala
>
a.reduceLeft(_ + _)
res0: Int = 6
scala
>
a.foldLeft(20)(_ + _)
res1: Int = 26
scala
>
a.foldLeft(100)(_ + _)
res2: Int = 106
scanLeft and scanRight
Two methods namedscanLeft
andscanRight
walk through a sequence in a manner similar toreduceLeft
andreduceRight
, but they return a sequence instead of a single value.
For instance,scanLeft
“Produces a collection containing cumulative results of applying the operator going left to right.” To understand how it works, create another function with a little debug code in it:
val product = (x: Int, y: Int) =
>
{
val result = x * y
println(s"multiplied $x by $y to yield $result")
result
}
Here’s whatscanLeft
looks like when it’s used with that function and a seed value:
scala
>
val a = Array(1, 2, 3)
a: Array[Int] = Array(1, 2, 3)
scala
>
a.scanLeft(10)(product)
multiplied 10 by 1 to yield 10
multiplied 10 by 2 to yield 20
multiplied 20 by 3 to yield 60
res0: Array[Int] = Array(10, 10, 20, 60)