4

如何在Scala集合上添加foreachWithIndex方法?用方法豐富Scala集合

這是我能想出迄今:

implicit def iforeach[A, CC <: TraversableLike[A, CC]](coll: CC) = new { 
    def foreachWithIndex[B](f: (A, Int) => B): Unit = { 
    var i = 0 
    for (c <- coll) { 
     f(c, i) 
     i += 1 
    } 
    } 
} 

這不起作用:

Vector(9, 11, 34).foreachWithIndex { (el, i) => 
    println(el, i) 
} 

引發以下錯誤:

error: value foreachWithIndex is not a member of scala.collection.immutable.Vector[Int] 
Vector(9, 11, 34).foreachWithIndex { (el, i) => 

然而代碼當我明確應用轉換方法時工作:

iforeach[Int, Vector[Int]](Vector(9, 11, 34)).foreachWithIndex { (el, i) => 
    println(el, i) 
} 

輸出:

(9,0) 
(11,1) 
(34,2) 

我如何讓它度過,即使沒有一個轉換方法的明確的應用嗎?謝謝。

回答

8

您需要延長的Iterable:

class RichIter[A, C](coll: C)(implicit i2ri: C => Iterable[A]) { 
    def foreachWithIndex[B](f: (A, Int) => B): Unit = { 
    var i = 0 
    for (c <- coll) { 
     f(c, i) 
     i += 1 
    } 
    } 
} 

implicit def iter2RichIter[A, C[A]](ca: C[A])(
    implicit i2ri: C[A] => Iterable[A] 
): RichIter[A, C[A]] = new RichIter[A, C[A]](ca)(i2ri) 

Vector(9, 11, 34) foreachWithIndex { 
    (el, i) => println(el, i) 
} 

輸出:

(9,0) 
(11,1) 
(34,2) 

更多信息請參見this post by Rex Kerr

4

簡短的回答是,如果你這樣做,或者類型推理器不能確定A是什麼,你必須參數化CC。另一個簡短的回答就是我在this question的回答中描述的方式。

要展開多一點點,真的沒有理由,你需要CC <: TraversableLike --just有它採取Traversableiforeach[A](coll: Traversable[A])開始!您不需要使用花式類型邊界來使用超類/超類。如果您希望在保存集合類型的情況下返回其他集合的情況下執行更復雜的操作,那麼您需要使用構建器等,這些在另一個問題中描述。

+0

其實它是由一組額外的方法只有一個方法我我正在努力實施。其他一些方法需要構建相同類型的新集合。 – missingfaktor

2

如果您感興趣的是隻有一個指標迭代什麼,你還不如干脆跳過這個拉皮條的一部分,這樣做

coll.zipWithIndex.foreach { case (elem, index) => 
    /* ... */ 
} 
+0

https://twitter.com/#!/missingfaktor/status/95597737680183297 :-) – missingfaktor

+0

那麼'mapWithIndex'呢?名單繼續。 –