地图展平和平面图不相同

Mik*_*yer 14 dictionary scala case-class

我认为Scala构造map(f).flatten相当于flatMap(f).但是通过这个例子,情况并非如此.我想知道案例类的作用是什么.如果我使用整数,两者都是等价的.但就我而言,我不能.

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
Run Code Online (Sandbox Code Playgroud)

产量

Set((CTest(0),3), (CTest(1), 2))
Run Code Online (Sandbox Code Playgroud)

而

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
Run Code Online (Sandbox Code Playgroud)

产量

Set((CTest(0),0), (CTest(0),3), (CTest(1),0), (CTest(1),2))
Run Code Online (Sandbox Code Playgroud)

知道为什么吗?

tir*_*ran 10

这是由于中间数据结构而发生的.

我将采用你的例子的简单版本.

val m = Map(CTest(0) -> List(0, 3), CTest(1) -> List(0, 2))
Run Code Online (Sandbox Code Playgroud)

使用flatMap时直接创建一个Map[CTest, Int]

scala> m flatMap {
 |     case (label, destNodes) => destNodes map {
 |       case nodes => (label, nodes) }
 |   }
res3: scala.collection.immutable.Map[CTest,Int] = Map(CTest(0) -> 3, CTest(1) -> 2)
Run Code Online (Sandbox Code Playgroud)

在这里,由于的键的唯一性Map,(CTest(0), 0)并且(CTest(1), 0)将结果被丢弃.当你flatMap超过设定,你会得到一个Set在Tuples其中Map.

在第二个示例中,您将映射并展平.

val mapping = m map {
 |     case (label, destNodes) => destNodes map {
 |       case nodes => (label, nodes) }
 |   }
mapping: scala.collection.immutable.Iterable[List[(CTest, Int)]] = List(List((CTest(0),0), (CTest(0),3)), List((CTest(1),0), (CTest(1),2)))

mapping.flatten
res4: scala.collection.immutable.Iterable[(CTest, Int)] = List((CTest(0),0), (CTest(0),3), (CTest(1),0), (CTest(1),2))
Run Code Online (Sandbox Code Playgroud)

Map在流程的中间没有创建任何或另一个唯一性保留的数据结构.所以价值不会下降.


che*_*dze 7

看一下实现flatMap:

def flatMap[B, That](f: A => GenTraversableOnce[B])(implicit bf: CanBuildFrom[Repr, B, That]): That = {
  def builder = bf(repr) // extracted to keep method size under 35 bytes, so that it can be JIT-inlined
  val b = builder
  for (x <- this) b ++= f(x).seq
  b.result
}
Run Code Online (Sandbox Code Playgroud)

结果flatMap取决于原始集合类型和函数的结果类型f.在第一个示例中,您将从map生成元组序列,以便编译器选择实现,例如CanBuildFrom[Map[A, B], (C, D), Map[C, D]],它提供构建器Map,从而导致覆盖相同的键.

您可以直接将map转换为plain iterable,这将产生您想要的结果:

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.toIterable.flatMap {
    case (label, destNodes) => destNodes map {
      case nodes => (label, nodes) }
  }
  mapping
}
possibilities
Run Code Online (Sandbox Code Playgroud)