How to use the ‘filter’ method to filter a Scala collection

This is an excerpt from 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.

Discussion

The main methods you can use to filter a collection are listed in Recipe 10.3, and are repeated here for your convenience:

  • collect
  • diff
  • distinct
  • drop
  • dropWhile
  • filter
  • filterNot
  • find
  • foldLeft
  • foldRight
  • head
  • headOption
  • init
  • intersect
  • last
  • lastOption
  • reduceLeft
  • reduceRight
  • remove
  • slice
  • tail
  • take
  • takeWhile
  • union

Unique characteristics of filter compared to these other methods include:

  • filter walks through all of the elements in the collection; some of the other methods stop before reaching the end of the collection
  • filter lets 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; filter doesn’t modify the collection it’s invoked on

See Also

  • The collect method 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”.

The Scala Cookbook

This tutorial is sponsored by the Scala Cookbook, which I wrote for O’Reilly:

You can find the Scala Cookbook at these locations:

Add new comment

The content of this field is kept private and will not be shown publicly.

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.