展平 Scala 尝试 [英] Flatten Scala Try
问题描述
是否有一种简单的方法来展平一组尝试值以给出尝试值的成功或失败?例如:
Is there a simple way to flatten a collection of try's to give either a success of the try values, or just the failure? For example:
def map(l:List[Int]) = l map {
case 4 => Failure(new Exception("failed"))
case i => Success(i)
}
val l1 = List(1,2,3,4,5,6)
val result1 = something(map(l1))
result1: Failure(Exception("failed"))
val l2 = List(1,2,3,5,6)
val result2 = something(map(l2))
result2: Try(List(1,2,3,5,6))
你将如何处理集合中的多个失败?
And can how would you handle multiple Failures in the collection?
推荐答案
也许不像你希望的那么简单,但它有效:
Maybe not as simple as you hoped for, but this works:
def flatten[T](xs: Seq[Try[T]]): Try[Seq[T]] = {
val (ss: Seq[Success[T]]@unchecked, fs: Seq[Failure[T]]@unchecked) =
xs.partition(_.isSuccess)
if (fs.isEmpty) Success(ss map (_.get))
else Failure[Seq[T]](fs(0).exception) // Only keep the first failure
}
val xs = List(1,2,3,4,5,6)
val ys = List(1,2,3,5,6)
println(flatten(map(xs))) // Failure(java.lang.Exception: failed)
println(flatten(map(ys))) // Success(List(1, 2, 3, 5, 6))
请注意,partition
的使用并不像它所获得的那样类型安全,正如 @unchecked
注释所证明的那样.在这方面,累积两个序列 Seq[Success[T]]
和 Seq[Failure[T]]
的 foldLeft
会更好.
Note that the use of partition
is not as type safe as it gets, as witnessed by the @unchecked
annotations. In that respect, a foldLeft
that accumulates two sequences Seq[Success[T]]
and Seq[Failure[T]]
would be better.
如果你想保留所有的失败,你可以使用这个:
If you wanted to keep all failures, you can use this:
def flatten2[T](xs: Seq[Try[T]]): Either[Seq[T], Seq[Throwable]] = {
val (ss: Seq[Success[T]]@unchecked, fs: Seq[Failure[T]]@unchecked) =
xs.partition(_.isSuccess)
if (fs.isEmpty) Left(ss map (_.get))
else Right(fs map (_.exception))
}
val zs = List(1,4,2,3,4,5,6)
println(flatten2(map(xs))) // Right(List(java.lang.Exception: failed))
println(flatten2(map(ys))) // Left(List(1, 2, 3, 5, 6))
println(flatten2(map(zs))) // Right(List(java.lang.Exception: failed,
// java.lang.Exception: failed))
这篇关于展平 Scala 尝试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!