60

What is the difference between the map and flatMap functions of Iterable?

Eugene Yokota
  • 94,654
  • 45
  • 215
  • 319
Landon Kuhn
  • 76,451
  • 45
  • 104
  • 130

5 Answers5

58

The above is all true, but there is one more thing that is handy: flatMap turns a List[Option[A]] into List[A], with any Option that drills down to None, removed. This is a key conceptual breakthrough for getting beyond using null.

oxbow_lakes
  • 133,303
  • 56
  • 317
  • 449
kikibobo
  • 1,217
  • 1
  • 9
  • 8
  • 3
    Aw, that's another nice trick with Option I never thought about. I just had a method return a list of 1 or more things, never saw the `Option.toList` method: List( Some( "foo" ), None, Some( "bar" ) ).flatMap( _.toList ) – Tristan Juricek Jul 01 '09 at 11:01
  • Or perhaps even better, use `Option.toIterator` with Tristan's method so that you don't iterate over the whole list until necessary. – Jonathan Schneider Jun 06 '14 at 16:40
45

Here is a pretty good explanation:

http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-2

Using list as an example:

Map's signature is:

map [B](f : (A) => B) : List[B]

and flatMap's is

flatMap [B](f : (A) => Iterable[B]) : List[B]

So flatMap takes a type [A] and returns an iterable type [B] and map takes a type [A] and returns a type [B]

This will also give you an idea that flatmap will "flatten" lists.

val l  = List(List(1,2,3), List(2,3,4))

println(l.map(_.toString)) // changes type from list to string
// prints List(List(1, 2, 3), List(2, 3, 4))

println(l.flatMap(x => x)) // "changes" type list to iterable
// prints List(1, 2, 3, 2, 3, 4)
agilefall
  • 3,876
  • 3
  • 31
  • 27
  • 13
    It's interesting to note that `l flatMap { x => x }` is *precisely* equivalent to `l.flatten` according to the monadic axioms. FlatMap is Scala's equivalent of the monadic `bind` operation (>>= in Haskell). I find it to be most useful on non-collections monads such as Option. When in conjunction with collections, it is most useful for implementing "nested map-loops", returning a collection as a result. – Daniel Spiewak Jun 29 '09 at 23:20
  • Well said. The chaining of Options is much better to work with than a bunch of statements like if(x != null and x.foo != null). http://blog.lostlake.org/index.php?/archives/50-The-Scala-Option-class-and-how-lift-uses-it.html discusses this in detail – agilefall Jun 29 '09 at 23:27
  • 1
    println(l.flatMap(x => x)) this doesn't work anymore and flatMap needs to be used like that : http://aperiodic.net/phil/scala/s-99/p07.scala – Olivier Girardot Aug 18 '11 at 10:14
8

From scaladoc:

  • map

Returns the iterable resulting from applying the given function f to each element of this iterable.

  • flatMap

Applies the given function f to each element of this iterable, then concatenates the results.

skaffman
  • 398,947
  • 96
  • 818
  • 769
8
lines.map(line => line split "\\W+") // will return a list of arrays of words
lines.flatMap(line => line split "\\W+") // will return a list of words

You can see this better in for comprehensions:

for {line <- lines
     word <- line split "\\W+"}
yield word.length

this translates into:

lines.flatMap(line => line.split("\\W+").map(word => word.length))

Each iterator inside for will be translated into a "flatMap", except the last one, which gets translated into a "map". This way, instead of returning nested collections (a list of an array of a buffer of blah, blah, blah), you return a flat collection. A collection formed by the elements being yield'ed -- a list of Integers, in this case.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
3

Look here: http://www.codecommit.com/blog/scala/scala-collections-for-the-easily-bored-part-2

"Search for flatMap" - there is a really good explanation of it there. (Basically it is a combination of "flatten" and "map" -- features from other languages).