如何将 Seq[Try] 转换为 Try[Seq]

pme*_*pme 2 scala

Futures一种简单的方法可以转换Seq[Future]Future[Seq]

Future.sequence(seqOfFutures)

我找不到与 . 类似的东西Try

它适用于foldLeft但我真正喜欢的会有类似的东西Try.sequence(seqOfTry)

不提供这样的功能有什么原因吗?

如何正确完成此操作?

语义:

成功的价值观列表:Success(Seq(1,2,3,4))

失败有两种可能:

  • 拳头失败Failure并返回。这是通过这个问题处理的:listtryt-to-trylistt-in-scala

  • 收集所有内容Failures并返回“复合”失败。

对于“复合”故障还有解决方案吗?

Tim*_*Tim 6

这是第二个问题的解决方案。

case class CompoundError(errs: List[Throwable]) extends Throwable

def toTry[T](list: List[Try[T]]): Try[List[T]] =
  list.partition(_.isSuccess) match {
    case (res, Nil) =>
      Success(res.map(_.get))
    case (_, errs) =>
      Failure(CompoundError(errs.collect { case Failure(e) => e }))
  }
Run Code Online (Sandbox Code Playgroud)

partition操作区分成功和失败,并match根据是否失败返回适当的值。


以前的解决方案:

case class CompoundError(errs: List[Throwable]) extends Throwable

def toTry[T](list: List[Try[T]]): Try[List[T]] = {
  val (res, errs) = list.foldLeft((List.empty[T], List.empty[Throwable])) {
    case ((res, errs), item) =>
      item match {
        case Success(t) => (t :: res, errs)
        case Failure(e) => (res, e :: errs)
      }
  }

  errs match {
    case Nil => Success(res.reverse)
    case _ => Failure(CompoundError(errs.reverse))
  }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*lic 5

根据路易斯的建议Validated是为错误累积而设计的,所以请traverse像这样考虑

la.traverse(_.toEither.toValidatedNec)
lb.traverse(_.toEither.toValidatedNec)
Run Code Online (Sandbox Code Playgroud)

哪个输出

res2: cats.data.ValidatedNec[Throwable,List[Int]] = Invalid(Chain(java.lang.RuntimeException: boom, java.lang.RuntimeException: crash))
res3: cats.data.ValidatedNec[Throwable,List[Int]] = Valid(List(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)

在哪里

import cats.syntax.traverse._
import cats.instances.list._
import cats.syntax.either._
import scala.util.{Failure, Success, Try}

val la: List[Try[Int]] = List(Success(1), Success(2), Failure(new RuntimeException("boom")), Success(3), Failure(new RuntimeException("crash")))
val lb: List[Try[Int]] = List(Success(1), Success(2), Success(3))
Run Code Online (Sandbox Code Playgroud)

如果没有错误累积,我们可以像这样排序

import cats.implicits._
la.sequence 
Run Code Online (Sandbox Code Playgroud)

哪个输出

res0: scala.util.Try[List[Int]] = Failure(java.lang.RuntimeException: boom)
Run Code Online (Sandbox Code Playgroud)

  • 我只是想补充一点,“Seq”(如问题中所使用的)没有“Traverse”实例。如果“List”没问题,那么这就是正确的选择。 (2认同)