我正在搜索特定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时。 不好。我该怎么办,所以我只计算一次?
由于
答案 0 :(得分: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
返回。不会再进行搜索。
答案 1 :(得分: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)
}
}
转换为Stream
是可选的,但可能更有效,因为它可以避免在找到所需元素时搜索整个向量。
答案 2 :(得分: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)
答案 3 :(得分:0)
这是一个易于理解的解决方案
foo