过滤Scala Either列表中的失败

时间:2015-01-22 14:10:08

标签: scala either

我有一个输入值列表

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
  }
}

有没有更简洁的方式来表达这种模式?

有时,我必须通过另一个函数进一步处理成功,再次使用相同的模式。例如

  • 将JSON数组转换为Scala模型,如果任何JSON对象格式错误,则会失败。
  • 将模型写入数据库,如果任何数据库更新失败,则会失败。

2 个答案:

答案 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)
 } 

其中lEither[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,因为它可以返回FailureSuccess列表