This code prints List(1, 2, ())
def f1(i:Int): Either[String,Int] = if (i > 0) Right(1) else Left("error 1")
def f2(i:Int): Either[String,Int] = if (i > 0) Right(2) else Left("error 2")
def f3(i:Int): Either[String,Int] = if (i > 0) Right(3) else Left("error 3")
val seq = Seq(f1(1),f2(1),f3(-1))
val x = seq.map { f => if (f.isRight) f.right.get }
println(x)
I need an array filtered by isRight
is true, eliminating any other values. In the example above, the result I would need is List(1, 2)
. How to achieve it?
答案 0 :(得分:15)
Use collect
and pattern match to select the case you are interested in.
seq.collect { case Right(value) => value}
Lets try on
scala> :paste
// Entering paste mode (ctrl-D to finish)
def f1(i:Int): Either[String,Int] = if (i > 0) Right(1) else Left("error 1")
def f2(i:Int): Either[String,Int] = if (i > 0) Right(2) else Left("error 2")
def f3(i:Int): Either[String,Int] = if (i > 0) Right(3) else Left("error 3")
val seq = Seq(f1(1),f2(1),f3(-1))
// Exiting paste mode, now interpreting.
f1: (i: Int)Either[String,Int]
f2: (i: Int)Either[String,Int]
f3: (i: Int)Either[String,Int]
seq: Seq[Either[String,Int]] = List(Right(1), Right(2), Left(error 3))
scala> seq.collect { case Right(value) => value }
res0: Seq[Int] = List(1, 2)
In
val x = seq.map { f => if (f.isRight) f.right.get }
The below returns Unit
in case f is not right. So, you get Unit
as third value.
if (f.isRight) f.right.get
Functional way is to use have else part also. But In this case, there is no meaningful else case.
答案 1 :(得分:5)
您必须记住,在Scala中,if
是一个返回值的表达式。在您的情况下,值为f.right.get
(Right
中存在Either
),否则为Unit
。要仅对Right
值进行过滤,请使用filter
:
val x = seq.filter(_.isRight).map(_.right.get)