将选项[T]添加到选项[Seq [T]]

时间:2018-06-25 18:05:42

标签: scala optional

我有一个Option[Seq[String]],试图找到一种向该集合添加Option[String]的最佳方法,从而再次产生一个Option[Seq[String]]。如果集合为None,但要添加的值为Some[String],则结果应为具有该单个值的Option[Seq[String]]

我想出了两种写方法,基本上可以归结为相同的方法。我觉得必须有更好的方法来做到这一点。有什么建议么?

val messages: Option[Seq[String]] = Some(Seq("item"))
val message: Option[String] = Some("item 2")

val opt1: Option[Seq[String]] = message match {
  case Some(message) => Some(messages.map(_ :+ message).getOrElse(Seq(message)))
  case None          => messages
}

val opt2: Option[Seq[String]] = message
  .map(msg => Some(messages.map(_ :+ msg).getOrElse(Seq(msg))))
  .getOrElse(messages)

println(opt1) // Some(List(item, item 2))
println(opt2) // Some(List(item, item 2))

4 个答案:

答案 0 :(得分:3)

messages可用时。将message转换为Seq并将其添加到现有消息中。

否则将message转换为Option[Seq[String]]

messages.map(msgs => msgs ++ message.toSeq)
  .orElse(message.map(x => Seq(x)))

清晰的语法

 messages.map(_ ++ message.toSeq) orElse message.map(Seq(_))

Scala REPL

scala> :paste
// Entering paste mode (ctrl-D to finish)

  def addOption[T](messages: Option[Seq[T]], message: Option[T]): Option[Seq[T]] =
    messages.map(msgs => msgs ++ message.toSeq)
      .orElse(message.map(Seq(_)))


// Exiting paste mode, now interpreting.

addOption: [T](messages: Option[Seq[T]], message: Option[T])Option[Seq[T]]

scala> addOption(Some(Seq(1)), Some(2))
res4: Option[Seq[Int]] = Some(List(1, 2))

scala> addOption(Some(Seq(1)), Some(3))
res5: Option[Seq[Int]] = Some(List(1, 3))

scala> addOption(Some(Seq(1)), None)
res6: Option[Seq[Int]] = Some(List(1))

scala> addOption(None, None)
res7: Option[Seq[Nothing]] = None

scala> addOption(None, Some(1))
res8: Option[Seq[Int]] = Some(List(1))

scala> addOption(None, Some(2))
res9: Option[Seq[Int]] = Some(List(2))

答案 1 :(得分:1)

这里是另一个:

def push[T](message: Option[T], messages: Option[Seq[T]]): Option[Seq[T]] =
  message.map(s => messages.getOrElse(Nil) :+ s).orElse(messages)

产生:

push(Some("!"), Some(Seq("hello", "world"))) // Some(List(hello, world, !))
push(None, Some(List("hello", "world")))     // Some(List(hello, world))
push(Some("!"), None)                        // Some(List(!))
push(None, None)                             // None

答案 2 :(得分:0)

这是使用fold的一种方法:

def addOptMsg[T](msgs: Option[Seq[T]], msg: Option[T]): Option[Seq[T]] =
  msgs.fold( msg.map(Seq(_)) )( s => Option(s ++ msg.toSeq) )

测试方法:

val messages: Option[Seq[String]] = Some(Seq("item1", "item2"))
val message: Option[String] = Some("item3")

val messages0: Option[Seq[String]] = None
val message0: Option[String] = None

addOptMsg(messages, message)
// res1: Option[Seq[String]] = Some(List(item1, item2, item3))

addOptMsg(messages, message0)
// res2: Option[Seq[String]] = Some(List(item1, item2))

addOptMsg(messages0, message)
// res3: Option[Seq[String]] = Some(List(item3))

addOptMsg(messages0, message0)
// res4: Option[Seq[String]] = None

答案 3 :(得分:0)

使用fold opt2变为:

val opt2: Option[Seq[String]] =
  message.fold(messages)(msg => Some(messages.fold(Seq(msg))(_ :+ msg)))

[由Intellij自动转换:)]