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
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!
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)
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.
Edit: 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)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With