I thought that Scala construct map(f).flatten
was equivalent to flatMap(f)
. But with this example, it is not the case. I wonder what is the role of the case class in it. If I use integers, both are equivalent. But in my case, I cannot.
case class CTest(v: Int)
val s = Set(Map(CTest(0) -> List(0, 3), CTest(1) -> List(0, 2)))
val possibilities = s flatMap { m =>
val mapping = m flatMap {
case (label, destNodes) => destNodes map {
case nodes => (label, nodes) }
}
mapping
}
possibilities
Yields
Set((CTest(0),3), (CTest(1), 2))
whereas
case class CTest(v: Int)
val s = Set(Map(CTest(0) -> List(0, 3), CTest(1) -> List(0, 2)))
val possibilities = s flatMap { m =>
val mapping = m map {
case (label, destNodes) => destNodes map {
case nodes => (label, nodes) }
}
mapping.flatten
}
possibilities
yields
Set((CTest(0),0), (CTest(0),3), (CTest(1),0), (CTest(1),2))
Any idea why?
Take a look at implementation of
flatMap
:Result of
flatMap
depends on original collection type and result type of functionf
. In first example you generate sequence of tuples from map, so that compiler picks implementation likeCanBuildFrom[Map[A, B], (C, D), Map[C, D]]
, which provides builder forMap
, that causes overwriting of same keys.You can directly convert map to plain iterable, that will yield result you want:
This happens due to intermediate data structures.
I'll take simple version of your example.
When using
flatMap
you directly create aMap[CTest, Int]
In here, due to the uniqueness of the keys of
Map
,(CTest(0), 0)
and(CTest(1), 0)
will be dropped from the result. when youflatMap
it over set, you will get aSet
ofTuples
which were in theMap
.In your second example, you map and flatten.
There isn't any
Map
or another uniqueness preserved data structure created in the middle of the process. So values are not dropped.