1

想要合并val A = Option(Seq(1,2))val B = Option(Seq(3,4))产生一个新的选项序列

val C = Option(Seq(1,2,3,4))

这个

val C = Option(A.getOrElse(Nil) ++ B.getOrElse(Nil)),

似乎比

val C = Option(A.toList.flatten ++ B.toList.flatten)

但是有更好的方法吗?我是对的,getOrElse它比 更快更轻toList.flatten吗?

4

3 回答 3

3

一个整洁的理解怎么样:

val Empty = Some(Nil)

val C = for {
  a <- A orElse Empty
  b <- B orElse Empty
} yield a ++ b

创建较少的中间选项。

或者,你可以做一个有点麻烦的模式匹配:

(A, B) match {
  case (None, None) => Nil
  case (None, sb@Some(b)) => sb
  case (sa@Some(a), None) => sa
  case (Some(a), Some(b)) => Some(a ++ b)
}

我认为这至少比双重展平创建的中间集合更少。

于 2016-09-26T20:10:30.713 回答
2

你的第一个案例:

// In this case getOrElse is not needed as the option is clearly not `None`.
// So, you can replace the following: 
val C = Option(A.getOrElse(Nil) ++ B.getOrElse(Nil))

// By this:
val C = Option(A.get ++ B.get) // A simple concatenation of two sequences.
C: Option[Seq[Int]] = Some(List(1, 2, 3, 4))

由于多种原因,您的第二种情况/选项是错误的。

val C = Option(A.toList.flatten ++ B.toList.flatten)

    Option[List[Int]] = Some(List(1, 2, 3, 4)) 
  1. 它返回不正确的类型 Option[List[Int]] 而不是 Option[Seq[Int]]

  2. 它不必要地调用toListA 和 B。您可以简单地添加选项并调用flatten它们。

  3. 它不是 DRY 并且冗余调用flatten两者A.toList&B.toList而它可以调用 flatten(A ++ B)

取而代之的是,您可以更有效地执行此操作:

val E = Option((A ++ B).flatten.toSeq) 
E: Option[Seq[Int]] = Some(List(1, 2, 3, 4))
于 2016-09-26T21:03:03.367 回答
1

使用foldLeft

Seq(Some(List(1, 2)), None).foldLeft(List.empty[Int])(_ ++ _.getOrElse(List.empty[Int]))
result: List[Int] = List(1, 2)

使用flatten两次

Seq(Some(Seq(1, 2, 3)), Some(4, 5, 6), None).flatten.flatten

result: Seq(1, 2, 3, 4, 5, 6)

斯卡拉 REPL

scala> val a = Some(Seq(1, 2, 3))
a: Some[Seq[Int]] = Some(List(1, 2, 3))

scala> val b = Some(Seq(4, 5, 6))
b: Some[Seq[Int]] = Some(List(4, 5, 6))

scala> val c = None
c: None.type = None

scala> val d = Seq(a, b, c).flatten.flatten
d: Seq[Int] = List(1, 2, 3, 4, 5, 6)
于 2016-09-26T20:04:16.430 回答