2013-05-12 75 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是可選的,但可能更有效,因爲它避免了搜索整個矢量,如果已經找到了所需的元素。

相關問題