我有一个矢量Vector,我正在访问以应用布尔函数。即。
Vector[Vector[T]]
我将执行某些事情
f(myVector(i)(j))
其中f的类型为T => Boolean
。
但是这不是边界检查,我不能得到一些非常优雅的东西。
我可以使用applyOrElse
:
myVector.applyOrElse(i, (_:Int) => Vector.empty).applyOrElse (j, (_:Int) => defaultT)
f(defaultT)
将返回false
但我希望我可以设置默认值而不是函数。
我可以使用电梯给我一个Option
,但它在第二级没有很好的构成:
myVector.lift(i) map (_.lift(j) map f getOrElse false) getOrElse false
哪种方法有效,但仍然很难阅读。
然后是标准的if / else块:
if (myVector.size <= i) false
else {
val myVector2 = levelVector(i)
if (myVector2.size <= j) false
else f(myVector2(j))
}
它似乎应该能够比我能够实现的更容易分解。如果我添加第三层,它会变得更加丑陋。
还有其他选择吗?
免责声明:这是根据课程的编程课程改编的
答案 0 :(得分:3)
从问题中获取以下代码:
myVector.lift(i) map (_.lift(j) map f getOrElse false) getOrElse false
这可以改写如下:
myVector.lift(i).flatMap(_.lift(j)).fold(false)(f)
或者,在Scala 2.10中引入fold
之前:
myVector.lift(i).flatMap(_.lift(j)).map(f).getOrElse(false)
关键思想是尽可能推迟对Option
进行展开(或映射)。这种方法很自然地推广到两个以上的维度。
这非常接近等同于for
- 你的答案中的理解(假设你打算在那里包括lift
),但是一旦你必须将理解包括在括号中我个人倾向于找到清楚的版本更清楚。
答案 1 :(得分:0)
我认为看起来很优雅的东西,即使看起来有点矫枉过正:
(for {
myVector2 <- myVector(i)
t <- myVector2(j)
} yield t) map f getOrElse false
这是明智的吗?它当然可读。这很慢吗?
答案 2 :(得分:0)
假设向量被命名为vec
,谓词被命名为pred
,则该表达式将产生正确的值:vec.lift(p.row).fold(false)(_.lift(p.col).fold(false)(pred(_))