This is an excerpt from the 1st Edition of the Scala Cookbook (partially modified for the internet). This is Recipe 10.17, “How to use filter to Filter a Scala Collection”
Problem
You want to filter the items in a collection to create a new collection that contains only the elements that match your filtering criteria.
Solution
As listed in Recipe 10.3, “Choosing a Collection Method to Solve a Problem”, a variety of methods can be used to filter the elements of an input collection to produce a new output collection. This recipe demonstrates the filter method.
To use filter on your collection, give it a predicate to filter the collection elements as desired. Your predicate should accept a parameter of the same type that the collection holds, evaluate that element, and return true to keep the element in the new collection, or false to filter it out. Remember to assign the results of the filtering operation to a new variable.
A predicate is just a method (or function) that returns a boolean value.
For instance, the following example shows how to create a list of even numbers from an input list using a modulus algorithm:
scala> val x = List.range(1, 10) x: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9) // create a list of all the even numbers in the list scala> val evens = x.filter(_ % 2 == 0) evens: List[Int] = List(2, 4, 6, 8)
As shown, filter returns all elements from a sequence that return true when your function/predicate is called. There’s also a filterNot method that returns all elements from a list for which your function returns false.
Tip: You can think of
filteras meaning retain.
Discussion
The main methods you can use to filter a Scala collection are listed in Recipe 10.3 of the Scala Cookbook, and are repeated here for your convenience:
collectdiffdistinctdropdropWhilefilterfilterNotfindfoldLeftfoldRightheadheadOptioninitintersectlastlastOptionreduceLeftreduceRightremoveslicetailtaketakeWhileunion
Unique characteristics of filter compared to these other methods include:
filterwalks through all of the elements in the collection; some of the other methods stop before reaching the end of the collectionfilterlets you supply a predicate to filter the elements
How you filter the elements in your collection is entirely up to your algorithm. The following examples show a few ways to filter a list of strings:
scala> val fruits = Set("orange", "peach", "apple", "banana")
fruits: scala.collection.immutable.Set[java.lang.String] = Set(orange, peach, apple, banana)
scala> val x = fruits.filter(_.startsWith("a"))
x: scala.collection.immutable.Set[String] = Set(apple)
scala> val y = fruits.filter(_.length > 5)
y: scala.collection.immutable.Set[String] = Set(orange, banana)
Your filtering function can be as complicated as needed. When your algorithm gets long, you can pass a multiline block of code into filter:
scala> val list = "apple" :: "banana" :: 1 :: 2 :: Nil
list: List[Any] = List(apple, banana, 1, 2)
scala> val strings = list.filter {
| case s: String => true
| case _ => false
| }
strings: List[Any] = List(apple, banana)
You can also put your algorithm in a separate method (or function) and then pass it into filter:
def onlyStrings(a: Any) = a match {
case s: String => true
case _ => false
}
val strings = list.filter(onlyStrings)
The following example demonstrates that you can filter a list as many times as needed:
def getFileContentsWithoutBlanksComments(canonicalFilename: String): List[String] = {
io.Source.fromFile(canonicalFilename)
.getLines
.toList
.filter(_.trim != "")
.filter(_.charAt(0) != '#')
}
The two keys to using filter are:
- Your algorithm should return true for the elements you want to keep and false for the other elements
- Remember to assign the results of the filter method to a new variable;
filterdoesn’t modify the collection it’s invoked on
See Also
- The
collectmethod can also be used as a filtering method. Because it uses partial functions, it’s described in detail in Recipe 9.8, “Creating Partial Functions”.
| this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |