2011-07-25 61 views
48

假設我有兩個數組:在Traversable的foreach方法中獲取當前元素的索引?

val ar1 = Array[String]("1", "2", "3") 
val ar2 = Array[String]("1", "2", "3", "4") 

現在爲ar1每一個元素,我想先串聯該元素與ar2相應的元素,然後打印出結果。其中一個辦法是這樣的:

List.range(0, ar1.size).foreach(i => println(ar1(i)+ar2(i))) 

這本來是更好,如果有一個foreach變種,讓我直接與ar1指數上班的第一構建整數列表,而不是。

也許有更好的辦法嗎?

+0

另請參見http://stackoverflow.com/questions/6833501/efficient-iteration-with-index-in-scala – Vadzim

回答

84

一個非常方便的方法是在元組上使用zipped方法。放入兩個集合,獲取一個函數的兩個參數!

(ar1,ar2).zipped.foreach((x,y) => println(x+y)) 

這是既方便編寫和快速,因爲你並不需要建立一個元組來存儲每對(你會與(ar1 zip ar2)),這你就必須重新拆開。當兩個集合中較短的一個用盡時,兩種形式的拉鍊停止。

如果你有更復雜的東西(例如,你需要做的索引數學),規範的解決方案是在索引號郵編:

ar1.zipWithIndex.foreach{ case(x,i) => println(x+ar2(i)) } 

您正在使用的方法更快速和緊湊做如下所示,一個可以是有用的:

ar1.indices.foreach(i => println(ar1(i)+ar2(i))) 

雖然這隻適用於如果第一個集合不再比第二個集合。您還可以指定您的範圍explecitly:

(0 until (ar1.size min ar2.size)).foreach(i => println(ar1(i)+ar2(i))) 

解決此問題。 (你可以看到爲什麼zipzipped是首選的,除非你所做的事情太複雜了,以至於無法輕鬆工作。)

如果它不是一個平行的集合(通常是不,除非你打電話.par),它也有可能,但不推薦,跟蹤與可變變量:

{ var i=-1; ar1.foreach{ x => i += 1; println(x+ar2(i)) } } 

有一個非常有限的情況下,這是必要的(例如,如果你想跳過或回溯一些其他收藏品);如果你可以避免這樣做,你通常會得到更容易推理的代碼。

+1

我沒有回答這個問題,因爲問題明確詢問'Traversable',而'Traversable'沒有'zipWithIndex' - 這很煩人。 –

+0

@WilfredSpringer - 這個問題並不問''Traversable',它只是表示想在某個時候使用'foreach'。 –

+0

不要誤解我的意思。我會投票答覆你的答案。我只是說這個問題是:「在* Traversable *的foreach方法中獲取當前元素的索引?」所以它的出發點似乎是「穿越」;至少這就是我*如何閱讀這個問題。 –

4

我並沒有機會來測試它,但是這應該做的伎倆:

ar1.zip(ar2).foreach(x => println(x._1 +x._2)) 
+0

通過添加變量修復了'_'的兩次使用。 –

3

zip將做到這一點:

ar1 zip ar2 foreach { p => println(p._1 + p._2) } 

這將產生:

11 
22 
33 

請注意,您不需要[String]泛型類型,將由編譯器引發:

val ar1 = Array("1", "2", "3") 
val ar2 = Array("1", "2", "3", "4") 
34

你這是怎麼用慣用的斯卡拉指數環:

scala> List("A", "B", "C").zipWithIndex foreach { case(el, i) => 
    | println(i + ": " + el) 
    | } 
0: A 
1: B 
2: C 

這裏是地道的斯卡拉的方式做你想在你的代碼來實現的:

scala> val arr1 = Array("1", "2", "3") 
arr1: Array[java.lang.String] = Array(1, 2, 3) 

scala> val arr2 = Array("1", "2", "3", "4") 
arr2: Array[java.lang.String] = Array(1, 2, 3, 4) 

scala> (arr1, arr2).zipped.map(_ + _) foreach println 
11 
22 
33 
+0

這也是一個非常好的答案。 – Jus12