IndexOf for 2D Vector in Scala

Let's 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 bit inefficient, as indexOf is called twice on the line containing the element. Is there a better way to do this without resorting to imperative code?

+5
source share
2 answers

It is not only ineffective, but also dangerous. What if we change a little?

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

It really looks like an expression for an 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) 

It may be too important, but it all translates to flatMap and filter under the hood. You could write it with this, but it is much more readable.

Edit: if you need fast execution, the recursive solution will match the score:

 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) } 
+8
source

Here is an alternative to the Yushi decision.

 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) } 
0
source

Source: https://habr.com/ru/post/1479469/


All Articles