This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 10.9, “How to loop over a Collection with foreach”.
Problem
You want to iterate over the elements in a Scala collection class with the foreach
method.
Solution
The foreach
method on Scala collections classes takes a function as an argument. The function you define should take an element as an input parameter, and should not return anything. The input parameter type should match the type stored in the collection. As foreach
executes, it passes one element at a time from the collection to your function until it reaches the last element in the collection.
Side Effects: The
foreach
method applies your function to each element of the collection, but it doesn’t return a value. Because it doesn’t return anything, it’s said that it’s used for its “side effect.”
As an example, a common use of foreach
is to output information:
scala> val x = Vector(1, 2, 3) x: scala.collection.immutable.Vector[Int] = Vector(1, 2, 3) scala> x.foreach((i: Int) => println(i)) 1 2 3
That’s the longhand way of writing that code. For most expressions, Scala can infer the type, so specifying i: Int
isn’t necessary:
args.foreach(i => println(i))
You can further shorten this expression by using the ubiquitous underscore wildcard character instead of using a temporary variable:
args.foreach(println(_))
In a situation like this, where a function literal consists of one statement that takes a single argument, it can be condensed to this form:
args.foreach(println)
For a simple case like this, the syntax in the last example is typically used.
Discussion
As long as your function (or method) takes one parameter of the same type as the elements in the collection and returns nothing (Unit
), it can be called from a foreach
method. In the following example, the printIt
method takes a Char
, does something with it, and returns nothing:
def printIt(c: Char) { println(c) }
Because a String
is a sequence of type Char
, printIt
can be called in a foreach
method on a String
as follows:
"HAL".foreach(c => printIt(c)) "HAL".foreach(printIt)
If your algorithm is used only once, you don’t have to declare it as a method or function; just pass it to foreach
as a function literal:
"HAL".foreach((c: Char) => println(c))
To declare a multiline function, use this format:
val longWords = new StringBuilder "Hello world it's Al".split(" ").foreach{ e => if (e.length > 4) longWords.append(s" $e") else println("Not added: " + e) }
To understand this example, it may be helpful to know the split
method used in that function creates an Array[String]
, as shown here:
scala> "Hello world it's Al".split(" ") res0: Array[java.lang.String] = Array(Hello, world, it's, Al)
In addition to using the foreach
method on sequential collections, it’s also available on the Map
class. The Map
implementation of foreach
passes two parameters to your function. You can handle those parameters as a tuple:
val m = Map("fname" -> "Tyler", "lname" -> "LeDude") m foreach (x => println(s"${x._1} -> ${x._2}"))
However, I generally prefer the following approach:
movieRatings.foreach { case(movie, rating) => println(s"key: $movie, value: $rating") }
See Also
- See Recipe 11.18, “How to traverse a Scala Map (Map class)”, for other ways to iterate over a map.
- Scala’s
for
loop provides another powerful way to iterate over the elements in a collection. See Recipe 10.10, “How to loop over a Scala collection with a ‘for’ loop”, for more information.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |