# Traversable ops – Map + Flatten = Flatmap *

One of the most frequently asked questions and that usually leads to confusion among those that are new to Scala is:

What’s the difference between map and flatMap?

## Map

`Map` function is the prime converter function. It transforms the elements that compose the Traversable into other elements of the same or different type. Its notation is, for a given `T[A]`:

```def map[B](f: A => B):T[B]
```

If we put an example,

```val myList: List[Int] = List(1,2,3)
val anotherList: List[String] =
myList.map((n:Int) => n.toString) //List("1","2","3")
```

we have that, given a list of integers, the transformation function `(n:Int) => n.toString` is applied to every member in the list, generating a new list whose type is the one that results from the transformation function, that is, `String` type.

Though this is not unique for `map` function, we should remember that there are shorter ways to define the transformation function:

```val f: Int => String = (n: Int) => n.toString
val f: Int => String = n => n.toString
val f: Int => String = _.toString
```

## flatMap

Well, `map` is now ok, understood, but then… what the hell is `flatMap`? In order to understand it, we need to make a short detour and get to know our helping function `flatten`.

## flatten

This operation, with the following signature:

```def flatten[B](implicit asTraversable: (A) => GenTraversableOnce[B]): Traversable[B]
```

allows us to flatten a traversable of traversables. That is to say, we flatten the collections that compose a collection. For instance:

```val l: List[List[Int]] = List(List(1,2,3),List(),List(4),List(5))
require(l.flatten==List(1,2,3,4,5)
```

The contained type doesn’t have to be the same as the container’s `List[List[Int]]`). It also applies to some other really interesting traversables, such as `Option[T]`:

```val l: List[Option[Int]] = List(Option(1),None,None,Option(2),Option(3))
require(l.flatten==List(1,2,3)
```

## flatMap (now seriously…)

Then, what is a `flatMap`? By now you might have gotten an idea 😉
It’s just that, the application of a `map` operation followed by a `flatten`.

Let’s put a practical example:

We have a function that gets a JSON object and a function that deserializes it, converting it into a map. It is possible that some fields in the JSON object have null value. How can we return a list with the non-null values?

A first approach could be…

```type KeyValueMap = Map[String,String]
type ValueList = List[String]
def fieldValues(obj: String, fieldDeser: String => KeyValueMap): ValueList = {
fieldDeser(obj).filter{
case (key,value) => value != null
}.values.toList
}
```

But, as David said, using nulls is not an option, and instead of that, we could write

```type KeyValueMap = Map[String,String]
type ValueList = List[String]
def fieldValues(obj: String, fieldDeser: String => KeyValueMap): ValueList = {
fieldDeser(obj).values.flatMap(Option(_)).toList
}
```

What has happened here? In detail, if we do the same operation but in two steps and simulate the input, we have tha

```val it: List[String] =
List("value1",null,"value3")//Simulating 'fieldDeser(ob).values'
val mapped: Iterable[Option[String]] =
it.map(Option(_)) //Remember Option(null)==None
require(mapped==List(Option("value1"),None,Option("value3")))
require(mapped.flatten==List("value1","value3"))
```

Now, I think we’ve finally answered to the million-dollar question.

Anuncios

## One response to “Traversable ops – Map + Flatten = Flatmap *”

1. […] are algebraic structures that have a constructor and a flatMap method which, as we already saw in previous posts, is a concatenation of a map method and a […]

Me gusta