5

我正在为特定的 int 搜索向量向量。

  def searchVectors(i: Int, vectors: Vector[Vector[Int]]) = {
    val x = vectors.indexWhere(_.indexWhere(_ == i))
    val y = vectors(x).indexOf(y)
    (x, y)
  }

你可以看到我得到了两次 y。首先在计算 x 时,然后在计算 y 时再次。不好。我该怎么做才能只计算 y 一次?

谢谢

4

4 回答 4

8

您可以采取的一种方法是迭代所有向量:

def searchVectors(x: Int, vec: Vector[Vector[Int]]) =
  for {
    i <- 0 until vec.size
    j <- 0 until vec(i).size
    if vec(i)(j) == x
  } yield (i, j)

Vector 也有zipWithIndex方法,它为集合的每个元素添加索引并创建它们的元组。因此,您可以使用它来归档相同的内容:

def searchVectors(x: Int, vec: Vector[Vector[Int]]) =
  for {
    (subVec, i) <- vec.zipWithIndex
    (elem, j) <- subVec.zipWithIndex
    if elem == x
  } yield (i, j)

这种方法的优点是,您使用的是内部循环而不是外部(基于索引)循环map/ flatMap。如果将其与视图结合使用,则可以实现惰性搜索:

def searchVectors(x: Int, vec: Vector[Vector[Int]]) =
  for {
    (subVec, i) <- vec.view.zipWithIndex
    (elem, j) <- subVec.view.zipWithIndex
    if elem == x
  } yield (i, j)

不是你仍然会收到结果集合,但它是惰性集合。因此,如果您要这样处理它:

searchVectors(3, vector).headOption

它实际上会执行搜索(仅在此时),然后,当它被找到时,它会以Option. 不会进行进一步的搜索。

于 2013-05-12T11:35:17.787 回答
3

这是一种更实用的方法:

def searchVectors(i: Int, vectors: Vector[Vector[Int]]) = {
  val outer = vectors.toStream map (_.indexOf(i))
  outer.zipWithIndex.filter(_._1 != -1).headOption map (_.swap)
}

编辑:我想我更喜欢这个:

def searchVectors(i: Int, vectors: Vector[Vector[Int]]) = {
  vectors.toStream.map(_.indexOf(i)).zipWithIndex.collectFirst {
    case (y, x) if y != -1 => (x, y)
  }
}

转换为 aStream是可选的,但可能更有效,因为如果已经找到所需的元素,它会避免搜索整个向量。

于 2013-05-12T12:53:57.493 回答
2

这也让我很困扰。您可能已经想到了这一点,但是如果您愿意违反不可变状态等函数式编程原则,这是一种可能的方法:

val v = Vector(Vector(1,2,3), Vector(4, 5, 6))
var c: Int = -1
val r = v.indexWhere(r => {c = r.indexOf(6); c != -1})
(r, c)
于 2018-10-25T17:12:23.553 回答
0

这是一个易于理解的解决方案

def searchVectors(i: Int, vectors: Vector[Vector[Int]]): (Int, Int) = {
    val row = vectors.indexWhere(_.contains(i)) // Try to get index of vector containing element
    if (row > -1) (row, vectors(row).indexOf(i)) // (row, col)
    else (-1, -1)
}
于 2019-02-19T10:57:15.073 回答