问题描述
假设我想找到一个元素在 2D 向量中第一次出现的索引.
Say I want to find the indices of the first occurrence of an element in a 2D Vector.
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 在包含该元素的行上被调用了两次.有没有更好的方法来做到这一点,而不必求助于命令式代码?
This seems a tad inefficient, as indexOf gets called twice on the row containing the element. Is there a better way to do this without having to resort to imperative code?
推荐答案
这不仅效率低下,而且还很危险.如果我们稍微修改一下呢?
It's not only inefficient, it's also dangerous. What if we modified it slightly?
val row = table indexWhere (_.indexOf(101) != -1)
val col = table(row) indexOf 42 //Uh-oh, IndexOutOfBounds!
这看起来真的很适合 for 表达式:
This really seems suited to a 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
.你可以用它来写它,但这更易读.
This might be too imperative, but it all gets transformed to flatMap
and filter
under the hood. You could write it with that, but this is far more readable.
如果您想要快速失败的行为,递归解决方案将符合要求:
If you want fail-fast behaviour, a recursive solution will fit the bill:
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)
}
这篇关于Scala 中二维向量的 indexOf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!