5

假设我想在 2D 向量中找到第一次出现的元素的索引。

val table = Vector.tabulate(10, 10)((x,y) => 10*x + y)
val row = table indexWhere (_.indexOf(42) != -1) // row = 4
val col = 
  if(row == -1) -1
  else table(row) indexOf 42 // col = 2

这似乎有点低效,因为 indexOf 在包含该元素的行上被调用了两次。有没有更好的方法来做到这一点而不必求助于命令式代码?

4

2 回答 2

9

这不仅效率低下,而且很危险。如果我们稍微修改一下呢?

val row = table indexWhere (_.indexOf(101) != -1) 
val col = table(row) indexOf 42 //Uh-oh, IndexOutOfBounds!

这似乎真的适合 for 表达式:

val z =
  for {
    i <- 0 until table.length
    j <- 0 until table(i).length
    if (table(i)(j) == 42)
  } yield (i, j)

z.headOption.getOrElse(-1, -1)

这可能过于迫切,但这一切都会转化为引擎盖下的flatMap内容。filter您可以用它来编写它,但这更具可读性。

编辑:如果您想要快速失败的行为,递归解决方案将符合要求:

def findElement(table: Vector[Vector[Int]], elem: Int): (Int, Int) = {
  @tailrec
  def feRec(row: Int, col: Int): (Int, Int) = {
    if (row == table.length) (-1, -1)
    else if (col == table(row).length) feRec(row + 1, 0)
    else if (table(row)(col) == elem) (row, col)
    else feRec(row, col + 1)
  }
  feRec(0, 0)
}
于 2013-05-07T05:02:45.177 回答
0

这是 Yuushi 解决方案的替代方案。

def findElement(table: Vector[Vector[Int]], elem: Int): (Int, Int) = {
    val row = table.indexWhere(_.contains(elem)) // Try to get index of vector containing element
    if (row > -1) (row, table(row).indexOf(elem)) // (row, col)
    else (-1, -1)
}
于 2019-02-19T10:02:38.020 回答