【问题标题】:Convert Scala `Seq[Option[A]]` to `Option[Seq[A]]` [duplicate]将 Scala `Seq[Option[A]]` 转换为 `Option[Seq[A]]` [重复]
【发布时间】:2021-08-31 14:41:04
【问题描述】:

我想知道 Scala 中的惯用方式是将Option[A]Seq 转换为Option[Seq[A]],如果任何输入选项为None,则结果为None

【问题讨论】:

标签: scala functional-programming optional


【解决方案1】:

惯用的方式可能是使用通常所说的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

【讨论】:

    【解决方案2】:

    标准库提供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
        }
    

    【讨论】:

    • 非常好,但使用Nil 会限制可能的集合类型。备选:.pipe(tup =&gt; if (tup._1.isEmpty) Some(tup._2) else None)
    猜你喜欢
    • 2019-03-03
    • 2020-07-16
    • 1970-01-01
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 2011-04-04
    • 2012-10-11
    • 1970-01-01
    相关资源
    最近更新 更多