【问题标题】:Combining two Option[List[String]] in Scala在 Scala 中组合两个 Option[List[String]]
【发布时间】:2017-03-01 20:39:11
【问题描述】:

我有两个选择

val opt1 = Some(List("Sal", "Salil"))
val opt2 = Some(List("Sal2", "Salil2"))

opt1 或 opt2 都可以是 None。如果其中一个是无,那么我想要一个选项,其中包含在另一个列表中。如果两者都是 None 则应该返回 None。

如果两者都是 Some 然后是 Some ,其列表包含两个列表中的元素,如下所示:

Some(List(Sal, Salil, Sal2, Salil2))

我知道我可以手动完成,但有没有一种优雅的方法可以做到这一点?如果选项之一是无,则无法理解。

【问题讨论】:

    标签: scala


    【解决方案1】:
    Option((opt1 ++ opt2).flatten.toList).filter(_.nonEmpty)
    

    【讨论】:

    • 如果两个输入都是Some(List()),这不会返回正确的值。这应该返回Some(List()),但您的解决方案返回None
    【解决方案2】:

    您可以使用带有 scalaz 或猫的半群附加很好地做到这一点:

    import scalaz._, Scalaz._ // for cats use `import cats._, implicits._`
    
    val opt1 = Option(List("Sal", "Salil"))
    val opt2 = Option(List("Sal2", "Salil2"))
    
    scala> opt1 |+| opt2
    res0: Option[List[String]] = Some(List(Sal, Salil, Sal2, Salil2))
    
    scala> opt1 |+| None
    res1: Option[List[String]] = Some(List(Sal, Salil))
    
    scala> Option.empty[List[String]] |+| None
    res2: Option[List[String]] = None
    

    否则,您可能需要使用标准库逐个处理:

    (opt1, opt2) match {
        case (Some(a), Some(b)) => Option(a ++ b)
        case (Some(a), None) => Option(a)
        case (None, Some(b)) => Option(b)
        case _ => None
    }
    

    或者使用收集方法将它们展平:

    scala> List(opt1, opt2).flatten.flatten
    res5: List[String] = List(Sal, Salil, Sal2, Salil2)
    
    scala> List(opt1, None).flatten.flatten
    res6: List[String] = List(Sal, Salil)
    

    【讨论】:

      【解决方案3】:

      我不认为只有一种适当的、优雅的方式可以实现这一目标。 有我的提议:

      val opt1 = Some(List("Sal", "Salil"))
      val opt2 = Some(List("Sal2", "Salil2"))
      
      def merge(xs: Option[Iterable[_]]*) = xs.flatten.reduceLeftOption(_ ++ _)
      

      有了结果:

      merge (opt1, opt2)
      res1: Option[Iterable[_]] = Some(List(Sal, Salil, Sal2, Salil2))
      
      merge (None, opt2)
      res2: Option[Iterable[_]] = Some(List(Sal2, Salil2))
      
      merge (opt1, None)
      res5: Option[Iterable[_]] = Some(List(Sal, Salil))
      
      merge (None, None)
      res6: Option[Iterable[_]] = None
      

      【讨论】:

        【解决方案4】:

        不需要flatten

        opt1.fold(opt2)(lst => Some(lst ++ opt2.getOrElse(Nil)))
        

        【讨论】:

          【解决方案5】:

          这是一个将++/flatten 方法与结尾处的match 相结合的变体。

          scala> :paste
          // Entering paste mode (ctrl-D to finish)
          
          val opt1 = Some(List("Sal", "Salil"))
          val opt2 = Some(List("Sal2", "Salil2"))
          val opt3 = None
          
          // Exiting paste mode, now interpreting.
          
          opt1: Some[List[String]] = Some(List(Sal, Salil))
          opt2: Some[List[String]] = Some(List(Sal2, Salil2))
          opt3: None.type = None
          
          scala> (opt1.toList ++ opt2.toList).flatten match { case Nil => None; case x => Some(x) }
          res0: Option[List[String]] = Some(List(Sal, Salil, Sal2, Salil2))
          
          scala> (opt1.toList ++ opt3.toList).flatten match { case Nil => None; case x => Some(x) }
          res1: Option[List[String]] = Some(List(Sal, Salil))
          
          scala> (opt3.toList ++ opt3.toList).flatten match { case Nil => None; case x => Some(x) }
          res2: Option[List[Nothing]] = None
          

          【讨论】:

            【解决方案6】:

            for 和 yield 的另一种用法:

              val xys = for {
                _  <- if(xs.isEmpty && ys.isEmpty) None else Some(List())
                x <-  if(xs.isDefined) xs else Some(List())
                y <- if(ys.isDefined) ys else Some(List())
              } yield List(x,y).flatten
            

            【讨论】:

            • 如果任一输入为None,则不会产生请求的结果。
            • 对,你是 jwvh,我更新了处理无的答案
            • 唉,如果两个输入都是None,现在它不会产生请求的结果。
            • @jwvh 我迟到了一年,但我又更新了答案!
            猜你喜欢
            • 1970-01-01
            • 2016-07-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-01-13
            • 1970-01-01
            • 2021-04-04
            • 2014-04-26
            相关资源
            最近更新 更多