8

我有一个向量向量,我正在访问它以应用布尔函数。IE

Vector[Vector[T]]我将按照 f(myVector(i)(j))where f is of type的方式执行一些操作T => Boolean

但这不会做边界检查,而且我不能得到真正优雅的东西。

我可以使用applyOrElsemyVector.applyOrElse(i, (_:Int) => Vector.empty).applyOrElse (j, (_:Int) => defaultT)

哪里f(defaultT)会返回false 但我希望我可以设置一个默认值而不是一个函数。

我可以使用 lift 给我一个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))
}

它似乎应该比我能实现的更容易分解。如果我添加第三层,它会变得更加丑陋。

还有其他选择吗?

免责声明:这是改编自 coursera 的 progfun 课程

4

3 回答 3

3

从问题中获取以下代码:

myVector.lift(i) map (_.lift(j) map f getOrElse false) getOrElse false

这可以重写如下:

myVector.lift(i).flatMap(_.lift(j)).fold(false)(f)

或者,之前fold在 Scala 2.10 中引入:

myVector.lift(i).flatMap(_.lift(j)).map(f).getOrElse(false)

Option关键思想是尽可能长时间地推迟展开(或映射) 。这种方法将很自然地推广到两个以上的维度。

这与您的答案中的 -comprehension 非常接近for(假设您打算在lift其中包含),但是一旦您必须将理解用括号括起来,我个人倾向于发现脱糖版本更清晰。

于 2013-11-04T10:21:47.577 回答
0

我想出了一些看起来很优雅的东西,即使它看起来有点矫枉过正:

(for {
   myVector2 <- myVector(i)
   t <- myVector2(j)
} yield t) map f getOrElse false

这是明智的吗?它当然是可读的。慢吗?

于 2013-11-04T09:57:22.203 回答
0

假设你的向量被命名vec并且你的谓词被命名pred,这个表达式将产生正确的值:vec.lift(p.row).fold(false)(_.lift(p.col).fold(false)(pred(_))

于 2020-08-06T20:02:41.000 回答