Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to capture inner matched value in indexWhere vector expression?

Tags:

scala

vector

Using a Vector[Vector[Int]] reference v, and the expression to find a given number num:

val posX = v.indexWhere(_.indexOf(num) > -1)

Is there any way to capture the value of _.indexOf(num) to use after the expression (i.e. the posY value)? The following signals an error 'Illegal start of simple expression':

val posX = v.indexWhere((val posY = _.indexOf(num)) > -1)
like image 909
Dan Avatar asked May 12 '13 01:05

Dan


2 Answers

If we do not mind using a variable then we can capture indexOf() value of inner Vector (_ in the below code) in a var and use it later to build the y position:

val posX = v.indexWhere(_.indexOf(num) > -1)
val posY = v(posX).indexOf(num)
like image 124
Blankslate Avatar answered Sep 24 '22 05:09

Blankslate


There are lots of nice functional ways to do this. The following is probably one of the more concise:

val v = Vector(Vector(1, 2, 3), Vector(4, 5, 6), Vector(7, 8, 9))
val num = 4

val Some((posY, posX)) = v.map(_ indexOf num).zipWithIndex.find(_._1 > -1)
// posY: Int = 0
// posX: Int = 1

Note that there's a lot of extra work going on here, though—we're creating a couple of intermediate collections, parts of which we don't need, etc. If you're calling this thing a lot or on very large collections, you unfortunately may need to take a more imperative approach. In that case I'd suggest bundling up all the unpleasantness:

def locationOf(v: Vector[Vector[Int]])(num: Int): Option[(Int, Int)] = {
  var i, j = 0
  var found = false

  while (i < v.size && !found) {
    j = 0

    while (j < v(i).size && !found)
      if (v(i)(j) == num) found = true else j += 1

    if (!found) i += 1
  }

  if (!found) None else Some(i, j)
}

Not as elegant, but this method is probably going to be a lot faster and more memory efficient. It's small enough that it isn't likely to contain any of the bugs that this kind of programming is so prone to, and it's referentially transparent—all the mutation is local.

like image 27
Travis Brown Avatar answered Sep 21 '22 05:09

Travis Brown