2011-07-25 13 views
48

は、私は2つの配列があると仮定:Traversableのforeachメソッドで現在の要素のインデックスを取得しますか?

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

次にar1の各要素のために、私は最初ar2の対応する要素とその要素を連結し、その結果を印刷します。私は最初の整数のリストを構築するのではなく、ar1のインデックスを直接操作することができるようになるforeachバリアントがあった場合、それはよりよいだっただろう

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

:行う1つの方法は、何かのようになります。

おそらくもっと良い方法がありますか?

+0

も参照してくださいhttp://stackoverflow.com/questions/6833501/efficient-iteration-with-index-in-scala – Vadzim

答えて

84

タプルのzippedメソッドを使用すると便利です。 2つのコレクションを入れ、関数に2つの引数を渡してください!

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

(あなたが(ar1 zip ar2)と同じように)あなたは再び離れて取るために持っている各ペアを格納するタプルを構築する必要がないので、これは、書くことが便利で速いの両方です。 2つのコレクションのうちの短いものが使い果たされると、両方の形式のジップが停止します。

あなたはもっと複雑なもの(例えば、あなたがインデックスに数学を行う必要があります)を持っている場合は、標準的な解決策は、インデックスにzip圧縮することです:

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

使用している方法は、より迅速かつコンパクトに行われています次のように便利です:

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

これは、最初のコレクションが2番目のコレクションよりも長くない場合にのみ有効です。また、範囲を明示的に指定することもできます。

(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 - 質問は_not_それだけでいくつかの点で 'foreach'を使用したい提案し、Traversable''について尋ねるん。 –

+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の方法である:

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

関連する問題