将一个Option[T]添加到一个Option[Seq[T]]中。

3

我有一个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个回答

4

当有 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))

这可以简化为 messages.map(_ ++ message.toSeq) orElse message.map(Seq(_)) - Tim

2
这里还有一个例子:
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

1
使用 fold 选项,opt2 变为:
val opt2: Option[Seq[String]] =
  message.fold(messages)(msg => Some(messages.fold(Seq(msg))(_ :+ msg)))

[ Intellij 自动转换 :) ]

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接