2013-05-12 43 views
4

我正在为特定的int搜索矢量矢量。获取2D矢量(矩阵)中的元素

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

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

感谢

+1

顺便说一句,我会命名项目查找为'x'或'z'或以某种方式除了'i'(i,j,k是索引) – 2013-05-12 11:28:32

+0

也你的代码不能编译 – soulcheck 2013-05-12 11:31:32

回答

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) 

矢量也有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

但isn' t指数在哪里shortcircuting而你的方法不是? (此外,它会返回集合,而不是单个元素) – 2013-05-12 11:37:24

+0

@ om-nom-nom是的,你是对的,我的解决方案,你会收到所有发现的向量元素。 – tenshi 2013-05-12 11:39:20

+0

@ om-nom-nom我更新了答案。通过使用视图,我实际上实现了短按需按需。 – tenshi 2013-05-12 11:54:23

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是可选的,但可能更有效,因为它避免了搜索整个矢量,如果已经找到了所需的元素。

相关问题