给予:
Seq(1,2,3) map {
case 1 => 11
case 2 => Seq(12,13,14)
case 3 => 15
}我如何优雅地将其简化为包含Seq[Int]的Seq(11,12,13,14,15)?
发布于 2015-05-21 08:03:05
有一种方法可以做到:
Seq(1,2,3) flatMap {
case 1 => Seq(11)
case 2 => Seq(12,13,14)
case 3 => Seq(15)
}res0: SeqInt = List(11,12,13,14,15)
发布于 2015-05-21 08:30:47
另一种方法是:
implicit def unitSeq[T](x: T): Seq[T] = Seq(x)
Seq(1, 2, 3) flatMap {
case 1 => 11
case 2 => Seq(12, 13, 14)
case 3 => 15
}res0: SeqInt = List(11,12,13,14,15)
发布于 2015-05-21 09:49:54
当你有了Seq(1,2,3),你就有了一个Seq[Int]。
但是,在地图操作之后,您遇到了一个问题。
val mapped = Seq(1,2,3) map {
case 1 => 11
case 2 => Seq(12,13,14)
case 3 => 15
}mapped的类型是什么?对此,一个合理的答案可能是它没有类型。这和事实很接近。结果类型是Seq[Any]。不幸的是,这是一种完全无用的类型。您不能以类型错误的方式对它做任何有用的事情,而且可以指出Scala不应该首先允许推断这种类型。
解决方案不是让它从一开始就走那么远,而是映射到确实有一种合理类型的东西。Simon提出的解决方案是一种合理的方法:
val mapped = Seq(1,2,3) map {
case 1 => Seq(11)
case 2 => Seq(12,13,14)
case 3 => Seq(15)
case _ => throw new Exception("uh oh, didn't account for this to happen!")
}现在映射的是一个Seq[Seq[Int]],我们可以用它做更多有用的事情,例如将它压平成一个带有mapped.flatten的Seq[Int]。
但我们可以一蹴而就。有一个名为flatMap on Seq[A]的操作,它接受一个函数A => Seq[A]作为它的参数,并返回一个Seq[A]。
val flatmapped = Seq(1,2,3) flatMap {
case 1 => Seq(11)
case 2 => Seq(12,13,14)
case 3 => Seq(15)
case _ => throw new Exception("uh oh, didn't account for this to happen!")
}flatmapped现在是Seq(11, 12, 13, 14, 15)
撇开
顺便说一下,在各种参数化类型上进行这个操作是非常有用的:(F[A], A => F[A]) => F[A]
例如:
Option[A].flatMap(a: A => Option[A]): Option[A]
def squareroot(x: Double): Option[Double] = if (x >= 0) Some(Math.sqrt(x))
else None
Some(4.0).flatMap(squareroot) == Some(2.0)
Some(-1.0).flatMap(squareroot) == None
None.flatMap(squareroot) == None或
Future[A].flatMap(a: A => Future[A]): Future[A]此操作有时称为flatMap,有时称为bind,有时表示为=>>,如果支持此操作的类型(称为F[A]),并支持另一个操作,该操作也可从A创建F[A] (有时称为point,有时称为return),并遵循关于这些操作如何组成的一些条件,F[A]形成Monad
https://stackoverflow.com/questions/30367807
复制相似问题