过滤Scala Either列表中的失败

Ral*_*lph 2 scala either

我有一个输入值列表

List[A]
Run Code Online (Sandbox Code Playgroud)

和一个功能

f(List[A]): Either[Failure, Success]
Run Code Online (Sandbox Code Playgroud)

我将该函数应用于列表的每个元素,从而产生一个List[Either[Failure, Success]].

我想检查列表,如果任何值失败,则返回第一个失败,否则返回成功列表.

我使用了以下模式:

val allValues = list.map(f(_))
if (allValues.exists(_.isLeft)) {
  allValues.find(_.isLeft).get
} else {
  allValues.collect {
    case Right(result) => result
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

Mic*_*jac 12

听起来好像你想把你List[Either[Failure, Success]]变成一个Either[Failure, List[Success]]?你可以使用它更优雅toLeft.

result collectFirst { case Left(f) => f } toLeft {
    result collect { case Right(r) => r}
}
Run Code Online (Sandbox Code Playgroud)

collectFirst接受PartialFunction[A, B]它将应用于List具有已定义输出的第一个元素,并将返回Option[B].在这种情况下,我尝试提取第一Left(f)List,所以我会得到Option[Failure].

然后,我打电话toLeftOption[Failure].这将转换为单Failure再次Left,如果Option包含一个值,参数将产生的Right值,如果Option是空的.

如果Option确实是空的,那么我使用collect类似于使用的方法来提取成功collectFirst,除了它保留ListPartialFunction为其定义的所有元素.