5

使用 Vector[Vector[Int]] 引用 v,以及查找给定数字 num 的表达式:

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

有什么方法可以捕获 _.indexOf(num) 的值以在表达式之后使用(即 posY 值)?以下表示错误“简单表达式的非法开始”:

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

4 回答 4

7

如果我们不介意使用变量,那么我们可以在 var 中捕获indexOf()内部 Vector(_在下面的代码中)的值,然后使用它来构建 y 位置:

val posX = v.indexWhere(_.indexOf(num) > -1)
val posY = v(posX).indexOf(num)
于 2013-05-12T20:02:55.050 回答
6

有很多很好的功能方法可以做到这一点。以下可能是更简洁的一种:

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

请注意,这里还有很多额外的工作要做——我们正在创建几个中间集合,其中一些我们不需要,等等。如果你经常调用这个东西或者在非常大的集合上,不幸的是,您可能需要采取更紧迫的方法。在这种情况下,我建议捆绑所有的不愉快:

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

不那么优雅,但这种方法可能会更快,内存效率更高。它足够小,不太可能包含这种编程容易出现的任何错误,而且它是引用透明的——所有的变异都是本地的。

于 2013-05-12T02:55:49.053 回答
2

从我的扶手椅上,

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

scala> v.zipWithIndex collectFirst {
     | case (e, i) if (e indexOf num) >= 0 =>
     |   (i, e indexOf num)
     | }
res7: Option[(Int, Int)] = Some((1,0))

我还没有完成扶手椅数学,但与 Travis 的相比,这是一个中间集合。但是请参阅 Travis 的评论,即结果内部索引在这里计算了两次,重点不是这样做。

于 2013-05-12T04:41:26.470 回答
0

这是一个解决方案,它只会在找到所需元素之前进行评估。我个人觉得它更具可读性,您可以跨程序重用它。如果需要,您显然可以使其更通用。

val v = Vector(Vector(1, 2, 3), Vector(4, 5, 6))

def findElem(i: Int, vs: Vector[Vector[Int]]): (Int, Int) =
    (for {
      row <- vs.indices.toStream
      col <- vs(row).indices.toStream
      if vs(row)(col) == i
    }  yield (row, col)).head

findElem(5, v) // (1, 1)

.toStream如果您想要所有职位,您可以删除这些方法。使用.toStreamjust 意味着您将只评估直到第一次出现。

于 2017-05-28T02:31:49.490 回答