我有一个输入值列表
List[A]
和一个功能
f(List[A]): Either[Failure, Success]
我将该函数应用于列表的每个元素,产生List[Either[Failure, Success]]
。
我想查看列表,如果任何值失败,则返回第一个失败,否则返回成功列表。
我使用了以下模式:
val allValues = list.map(f(_))
if (allValues.exists(_.isLeft)) {
allValues.find(_.isLeft).get
} else {
allValues.collect {
case Right(result) => result
}
}
和
val allValues = list.map(f(_))
val failures = allValues.collect { case Left(error) => error }
if (failures.nonEmpty) {
failures(0)
} else {
allValues.collect {
case Right(result) => result
}
}
有没有更简洁的方式来表达这种模式?
有时,我必须通过另一个函数进一步处理成功,再次使用相同的模式。例如
答案 0 :(得分:11)
听起来好像您希望将List[Either[Failure, Success]]
转换为Either[Failure, List[Success]]
?您可以使用toLeft
使其更加优雅。
result collectFirst { case Left(f) => f } toLeft {
result collect { case Right(r) => r}
}
collectFirst
接受PartialFunction[A, B]
它将应用于具有已定义输出的List
的第一个元素,并将返回Option[B]
。在这种情况下,我尝试从Left(f)
中提取第一个List
,因此我会得到Option[Failure]
。
然后,我在toLeft
上致电Option[Failure]
。如果Failure
包含值,则会将单Left
再次转换为Option
,如果Right
为空,则参数将生成Option
值。
如果Option
确实为空,那么我使用collect
提取成功,类似于使用collectFirst
,除了它保留List
的所有元素PartialFunction
的定义是。
答案 1 :(得分:1)
这应该有效
l.collectFirst { case Left(error) => error }.getOrElse {
l.map(_.right)
}
其中l
是Either[Left, Right]
例如:
如果出现错误
val l = List(Right(1), Right(2), Left(3), Left(4), Right(5))
l.collectFirst { case Left(error) => error }.getOrElse {
l.map(_.right)
} //res0: Any = 3
返回any
,因为它可以返回Failure
或Success
列表