假设我想找到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在包含该元素的行上被调用两次。有没有更好的方法来做到这一点,而不必诉诸命令式代码?
答案 0 :(得分:8)
这不仅效率低下,而且危险。如果我们稍微修改一下怎么办?
val row = table indexWhere (_.indexOf(101) != -1)
val col = table(row) indexOf 42 //Uh-oh, IndexOutOfBounds!
这看起来非常适合for-expression:
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)
}
答案 1 :(得分: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)
}