【问题标题】:Filtering a Scala Either list for failures过滤 Scala 列表中的失败
【发布时间】:2015-01-22 14:10:08
【问题描述】:

我有一个输入值列表

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 对象格式错误,则会失败。
  • 将模型写入数据库并在任何数据库更新失败时失败。

【问题讨论】:

    标签: scala either


    【解决方案1】:

    听起来好像您希望将 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]。在这种情况下,我尝试从List 中提取第一个Left(f),所以我会得到Option[Failure]

    然后,我在Option[Failure] 上拨打toLeft。如果Option 包含一个值,这会将单个Failure 再次转换为Left,如果Option 为空,则该参数将产生Right 值。

    如果Option 确实为空,那么我使用collect 提取成功,类似于使用collectFirst,除了它保留List 中定义PartialFunction 的所有元素。

    【讨论】:

    • 太好了!然后进行模式匹配以选择左或右。
    【解决方案2】:

    这应该可以工作

    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的列表

    【讨论】:

    • 您可以使用collectFirst替换组合collect + headOptiion
    • @RégisJean-Gilles - 很棒的建议......不知道 :) 编辑了答案
    猜你喜欢
    • 2021-02-09
    • 2016-11-15
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    • 2016-02-05
    • 2015-11-28
    • 2023-03-12
    • 1970-01-01
    相关资源
    最近更新 更多