假设我有一个Option[A => Boolean]
,一个List[A]
,以及我想对该列表的一个子集执行的一些操作。如果设置了该选项,那么我想首先过滤列表然后应用我的操作。如果没有,那么我想将它应用于整个列表。一个例子:
val a : Option[Int => Boolean] = Option((a : Int) => a % 2 == 0)
val b = 1 to 100
我可以轻松地执行以下操作:
val c = if (a.isDefined) b.filter(a.get) else b
但是,这涉及到a.get
;很多条件让我无法做到这一点!我也可以这样做:
val c = b.filter(a.getOrElse(_ => true))
这感觉更好,但现在我仍然坚持为我序列的每个元素执行第二次(尽管是微不足道的)操作。我希望它会被优化,但这仍然感觉不完美。
我想要的是缺少任何缺陷的东西。感觉应该有一个很好的方法 - 任何想法?
答案 0 :(得分:10)
您只需要使用正常的选项处理方法:
a.map(b.filter).getOrElse(b)
答案 1 :(得分:3)
与Rex Kerr的解决方案基本相同,但使用Scalaz的fold
使其更简洁。
一般来说,x.fold(f, g)
≡x.map(f).getOrElse(g)
。
scala> import scalaz._, Scalaz._
import scalaz._
import Scalaz._
scala> a.fold(b.filter, b)
res112: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100)
答案 2 :(得分:1)
如何将a更改为:
val a : Option[Seq[Int] => Seq[Int]] = Option((a : Seq[Int]) => a.filter(_ % 2 == 0))
val b = 1 to 100
val c = a.getOrElse((f:Seq[Int]) => f)(b)
(注意我没有尝试过上述内容,但它应该给你一个想法)
答案 3 :(得分:1)
我个人更喜欢模式匹配的清晰度;这是从你的散文描述到代码的非常直接的翻译:
val c = a match {
case Some(f) => b.filter(f)
case None => b
}