# How to filter a Scala Map (filterKeys, retain, transform)

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 11.22, “How to Filter a Scala Map”

## Problem

You want to filter the elements contained in a Scala `Map`, either by directly modifying a mutable map, or by applying a filtering algorithm on an immutable map to create a new map.

## Solution

Use the `retain` method to define the elements to retain when using a mutable map, and use `filterKeys` or `filter` to filter the elements in a mutable or immutable map, remembering to assign the result to a new variable.

## Filtering mutable maps

You can filter the elements in a mutable map using the `retain` method to specify which elements should be retained:

```scala> var x = collection.mutable.Map(1 -> "a", 2 -> "b", 3 -> "c")
x: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 1 -> a, 3 -> c)

scala> x.retain((k,v) => k > 1)
res0: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 3 -> c)

scala> x
res1: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 3 -> c)```

As shown, `retain` modifies a mutable map in place. As implied by the anonymous function signature used in that example:

`(k,v) => ...`

your algorithm can test both the key and value of each element to decide which elements to retain in the map.

In a related note, the `transform` method doesn’t filter a map, but it lets you transform the elements in a mutable map:

```scala> x.transform((k,v) => v.toUpperCase)
res0: scala.collection.mutable.Map[Int,String] = Map(2 -> B, 3 -> C)

scala> x
res1: scala.collection.mutable.Map[Int,String] = Map(2 -> B, 3 -> C)```

Depending on your definition of “filter,” you can also remove elements from a map using methods like `remove` and `clear`, which are shown in Recipe 11.16.

## Mutable and immutable maps

When working with a mutable or immutable map, you can use a predicate with the `filterKeys` methods to define which map elements to retain. When using this method, remember to assign the filtered result to a new variable:

```scala> val x = Map(1 -> "a", 2 -> "b", 3 -> "c")
x: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 1 -> a, 3 -> c)

scala> val y = x.filterKeys(_ > 2)
y: scala.collection.Map[Int,String] = Map(3 -> c)```

The predicate you supply should return `true` for the elements you want to keep in the new collection and `false` for the elements you don’t want.

If your algorithm is longer, you can define a function (or method), and then use it in the `filterKeys` call, rather than using an anonymous function. First define your method, such as this method, which returns `true` when the value the method is given is 1:

```scala> def only1(i: Int) = if (i == 1) true else false
only1: (i: Int)Boolean```

Then pass the method to the `filterKeys` method:

```scala> val x = Map(1 -> "a", 2 -> "b", 3 -> "c")
x: scala.collection.mutable.Map[Int,String] = Map(2 -> b, 1 -> a, 3 -> c)

scala> val y = x.filterKeys(only1)
y: scala.collection.Map[Int,String] = Map(1 -> a)```

In an interesting use, you can also use a `Set` with `filterKeys` to define the elements to retain:

```scala> var m = Map(1 -> "a", 2 -> "b", 3 -> "c")
m: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b, 3 -> c)

scala> val newMap = m.filterKeys(Set(2,3))
newMap: scala.collection.immutable.Map[Int,String] = Map(2 -> b, 3 -> c)```

You can also use all of the filtering methods that are shown in Chapter 10. For instance, the `Map` version of the `filter` method lets you filter the map elements by either key, value, or both. The `filter` method provides your predicate a `Tuple2`, so you can access the key and value as shown in these examples:

```scala> var m = Map(1 -> "a", 2 -> "b", 3 -> "c")
m: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b, 3 -> c)

// access the key
scala> m.filter((t) => t._1 > 1)
res0: scala.collection.immutable.Map[Int,String] = Map(2 -> b, 3 -> c)

// access the value
scala> m.filter((t) => t._2 == "c")
res1: scala.collection.immutable.Map[Int,String] = Map(3 -> c)```

The `take` method lets you “take” (keep) the first N elements from the map:

```scala> m.take(2)
res2: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b)```

See the filtering recipes in Chapter 10 for examples of other methods that you can use, including `takeWhile`, `drop`, `slice`, and more.