A collection of Scala ‘flatMap’ examples
Scala
Sure. When I was first trying to learn Scala, and cram the collections'
You can see this by running
Once again it’s worth noting that
See that page for more
This first example invokes
This morning (Nov. 2, 2012), I saw the following additional flatMap examples in a new presentation by Marius:
That example comes from this page. If you look at that page, you’ll see that the other examples use
If you have any flatMap examples you want to share, or improvements to the code shown, just leave a note in the Comments section.
Also, here's a repeat of those earlier links:
flatMap
FAQ: Can you share some Scala flatMap examples?Sure. When I was first trying to learn Scala, and cram the collections'
flatMap
method into my brain, I scoured books and the internet for great flatMap
examples. Once I had a little grasp of it I started creating my own
examples, and tried to keep them simple. I share those examples in this
tutorial.Using flatMap on a list of Strings
To get started, the following examples show the differences betweenmap
and flatMap
on a Seq[String]
:scala> val fruits = Seq("apple", "banana", "orange") fruits: Seq[java.lang.String] = List(apple, banana, orange) scala> fruits.map(_.toUpperCase) res0: Seq[java.lang.String] = List(APPLE, BANANA, ORANGE) scala> fruits.flatMap(_.toUpperCase) res1: Seq[Char] = List(A, P, P, L, E, B, A, N, A, N, A, O, R, A, N, G, E)Quite a difference, right? Because
flatMap
treats a String
as a sequence of Char
, it flattens the resulting list of strings into a sequence of characters (Seq[Char]
). I like to think of flatMap
as a combination of map
followed by flatten
, so it first runs map
on the sequence, then runs flatten
, giving the result shown.You can see this by running
map
and then flatten
yourself:scala> val mapResult = fruits.map(_.toUpperCase) mapResult: Seq[String] = List(APPLE, BANANA, ORANGE) scala> val flattenResult = mapResult.flatten flattenResult: Seq[Char] = List(A, P, P, L, E, B, A, N, A, N, A, O, R, A, N, G, E)
Tip: I often refer toflatMap
asmapFlat
so I can remember how it works.
Using a list of Options with map and flatMap
The following examples show more differences betweenmap
and flatMap
for a simple String
to Int
conversion example. Given this toInt
method:def toInt(s: String): Option[Int] = { try { Some(Integer.parseInt(s.trim)) } catch { // catch Exception to catch null 's' case e: Exception => None } }Here are a few examples to show how
map
and flatMap
work on a simple list of strings that you want to convert to Int:scala> val strings = Seq("1", "2", "foo", "3", "bar") strings: Seq[java.lang.String] = List(1, 2, foo, 3, bar) scala> strings.map(toInt) res0: Seq[Option[Int]] = List(Some(1), Some(2), None, Some(3), None) scala> strings.flatMap(toInt) res1: Seq[Int] = List(1, 2, 3) scala> strings.flatMap(toInt).sum res2: Int = 6
flatMap
does a nice job of flattening a list that has Some
and None
values in it.Once again it’s worth noting that
flatMap
is equivalent to running map
and then flatten
:scala> val mapResult = strings.map(toInt) mapResult: Seq[Option[Int]] = List(Some(1), Some(2), None, Some(3), None) scala> val flattenResult = mapResult.flatten flattenResult: Seq[Int] = List(1, 2, 3)
flatMap with another function
The following code is not mine (see the URL below), but it does a great job of demonstratingflatMap
when given the simple method g
, where g
returns three Int
values when given one Int
as input. That is, it transforms the single Int
to the three resulting Int
s:scala> val list = List(1,2,3,4,5) list: List[Int] = List(1, 2, 3, 4, 5) scala> def g(v:Int) = List(v-1, v, v+1) g: (v: Int)List[Int] scala> list.map(x => g(x)) res0: List[List[Int]] = List(List(0, 1, 2), List(1, 2, 3), List(2, 3, 4), List(3, 4, 5), List(4, 5, 6)) scala> list.flatMap(x => g(x)) res1: List[Int] = List(0, 1, 2, 1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6)This great example comes from the following URL:
See that page for more
map
and flatMap
examples.Convert Map values to a sequence with flatMap
Here's an interesting use offlatMap
I just thought about. Although there are other ways to get the values from a Scala map
, you can use flatMap
for this purpose:scala> val map = Map(1 -> "one", 2 -> "two", 3 -> "three") map: scala.collection.immutable.Map[Int,java.lang.String] = Map(1 -> one, 2 -> two, 3 -> three) scala> 1 to map.size flatMap(map.get) res0: scala.collection.immutable.IndexedSeq[java.lang.String] = Vector(one, two, three)By contrast, notice what the
map
method gives you:scala> 1 to map.size map(map.get) res1: scala.collection.immutable.IndexedSeq[Option[java.lang.String]] = Vector(Some(one), Some(two), Some(three))If you're new to Scala, note that the flatMap example is the same as this line of code, which may be more understandable:
1 to map.size flatMap(map.get(_))Again, probably not ideal, but I'm just trying to throw different ideas out here.
flatMap examples from Twitter documentation
The folks at Twitter have put out some excellent Scala documentation, including a collection offlatMap
examples that I've found in two different documents.This first example invokes
flatMap
twice on a sequence of characters:val chars = 'a' to 'z' val perms = chars flatMap { a => chars flatMap { b => if (a != b) Seq("%c%c".format(a, b)) else Seq() } }Can you guess what
perms
looks like? Here is some of it:perms: scala.collection.immutable.IndexedSeq[String] = Vector(ab, ac, ad, ae, af, ag, ah, ai, aj ... // goes on until ... zw, zx, zyThey also show the following example of
flatMap
with Option
. Remember that an Option
is a container of 0 or 1 things, then guess what this code does:val host: Option[String] = .. val port: Option[Int] = .. val addr: Option[InetSocketAddress] = host flatMap { h => port map { p => new InetSocketAddress(h, p) } }Those two examples came from Twitter's Effective Scala document, which is an excellent doc.
This morning (Nov. 2, 2012), I saw the following additional flatMap examples in a new presentation by Marius:
Seq(1,2,3,4) flatMap { x => Seq(x, -x) } // results in: res0: Seq[Int] = List(1, -1, 2, -2, 3, -3, 4, -4)Again this might be easier to understand if you look at
map
and then flatten
:scala> Seq(1,2,3,4) map { x => | Seq(x, -x) | } res1: Seq[Seq[Int]] = List(List(1, -1), List(2, -2), List(3, -3), List(4, -4)) scala> res1.flatten res2: Seq[Int] = List(1, -1, 2, -2, 3, -3, 4, -4)Here's the second example from that presentation:
Seq(1,2,3,4) flatMap { x => if (x%2 == 0) Seq(x) else Seq() } // results in: res1: Seq[Int] = List(2, 4)
flatMap in the Play Framework
Here’s an example offlatMap
being used in a Play Framework method:That example comes from this page. If you look at that page, you’ll see that the other examples use
map
, but this particular example uses flatMap
. It’s an interesting exercise to look at those examples and wonder why this is.Scala flatmap examples - Summary
I hope it helps to show some Scala flatMap examples, without too much discussion for the moment. In the end, flatMap is just a combination of map and flatten, so if map leaves you with a list of lists (or strings), add flatten to it. If that gives you what you need, call flatMap instead of map and flatten. After a while your brain will naturally think "flat map" without needing those intermediate steps.If you have any flatMap examples you want to share, or improvements to the code shown, just leave a note in the Comments section.
Also, here's a repeat of those earlier links:
best post.
RépondreSupprimerscala online training