2012-12-28 17 views
1

Scala的列表類有indexWhere方法,它們返回與提供的謂詞相匹配的List元素的單個索引(如果不存在,則返回-1)。Scala的List類應該有一個indicesWhere方法嗎?

我最近發現自己想要收集所有指數中匹配一個給定的謂詞列表,並發現自己編寫的表達式,如:

list.zipWithIndex.filter({case (elem, _) => p(elem)}).map({case (_, index) => index}) 

其中p這裏是選擇匹配的元素一些謂詞函數。對於這樣一個簡單的要求來說,這看起來似乎有些笨拙(但我可能會錯過一兩個技巧)。

我多少希望找到列表中的indicesWhere功能,這將允許我,而不是寫:

list.indicesWhere(p) 

如果這樣的事情是Scala的列表API的一部分,或者是有一個更簡單的表達比我在上面展示的做同樣的事情?

回答

3

嗯,這裏是一個較短的表達,消除一些你在你的(修改用特拉維斯的建議)句法噪聲:

list.zipWithIndex.collect { case (x, i) if p(x) => i } 

或者:

for ((x,i) <- list.zipWithIndex if p(x)) yield i 

但是如果你使用這個頻繁,你應該只是一個DD它作爲一個隱式方法:

class EnrichedWithIndicesWhere[T, CC[X] <: Seq[X]](xs: CC[T]) { 
    def indicesWhere(p: T => Boolean)(implicit bf: CanBuildFrom[CC[T], Int, CC[Int]]): CC[Int] = { 
    val b = bf() 
    for ((x, i) <- xs.zipWithIndex if p(x)) b += i 
    b.result 
    } 
} 
implicit def enrichWithIndicesWhere[T, CC[X] <: Seq[X]](xs: CC[T]) = new EnrichedWithIndicesWhere(xs) 

val list = List(1, 2, 3, 4, 5) 
def p(i: Int) = i % 2 == 1 
list.indicesWhere(p)   // List(0, 2, 4) 
+0

1由於爲有用的答案。但問題仍然存在,如果這個函數真的被包含在Scala集合API的一部分中?儘管有隱含的方法解決方法,但在我看來,對於相當基礎的操作來說,這仍然是一種不直觀的表達方式。 – Henry

+0

@Henry:Scala是開源的,隨時爲問題跟蹤器創建問題,編寫實現和測試,提供更改文檔並在GitHub上提出請求。你還想聽聽什麼?當沒有人從事這項工作時,如果有用的東西通常是無關緊要的。 – sschaef

3

你可以使用解壓到更換地圖:

list.zipWithIndex.filter({case (elem, _) => p(elem)}).unzip._2 
+3

或(更簡明和潛在的更有效):'list.zipWithIndex.collect {情況下(E,I)如果P(E)=> I}' –

相關問題