将 Scala `Seq[Option[A]]` 转换为 `Option[Seq[A]]`
Convert Scala `Seq[Option[A]]` to `Option[Seq[A]]`
我想知道在 Scala 中将 Option[A]
的 Seq
转换为 Option[Seq[A]]
的惯用方式是什么,如果有的话,结果是 None
的输入选项是 None
.
惯用的方式大概就是用一般所谓的traverse
.
我建议阅读有关它的 Cats 文档:https://typelevel.org/cats/typeclasses/traverse.html
有了 Cats,它就像:
import cats.implicits
val list = List(Some(1), Some(2), None)
// list: List[Option[Int]] = List(Some(1), Some(2), None)
val traversed = list.traverse(identity)
// traversed: Option[List[Int]] = None
// Or in this specific case:
val sequenced = list.sequence
// sequenced: Option[List[Int]] = None
标准库提供 partitionMap
帮助实现 sequence
操作
_.partitionMap(_.toRight("")) match {
case (Nil, xs) => Some(xs)
case _ => None
}
这是一个可能的通用实现作为扩展方法
extension [CC[x] <: IterableOps[x, CC, CC[x]], A](xs: CC[Option[A]])
def sequence: Option[CC[A]] =
xs.partitionMap(_.toRight("")) match {
case (lefts, as) if lefts.isEmpty => Some(as)
case _ => None
}
我想知道在 Scala 中将 Option[A]
的 Seq
转换为 Option[Seq[A]]
的惯用方式是什么,如果有的话,结果是 None
的输入选项是 None
.
惯用的方式大概就是用一般所谓的traverse
.
我建议阅读有关它的 Cats 文档:https://typelevel.org/cats/typeclasses/traverse.html
有了 Cats,它就像:
import cats.implicits
val list = List(Some(1), Some(2), None)
// list: List[Option[Int]] = List(Some(1), Some(2), None)
val traversed = list.traverse(identity)
// traversed: Option[List[Int]] = None
// Or in this specific case:
val sequenced = list.sequence
// sequenced: Option[List[Int]] = None
标准库提供 partitionMap
帮助实现 sequence
操作
_.partitionMap(_.toRight("")) match {
case (Nil, xs) => Some(xs)
case _ => None
}
这是一个可能的通用实现作为扩展方法
extension [CC[x] <: IterableOps[x, CC, CC[x]], A](xs: CC[Option[A]])
def sequence: Option[CC[A]] =
xs.partitionMap(_.toRight("")) match {
case (lefts, as) if lefts.isEmpty => Some(as)
case _ => None
}