1. 概要

このチュートリアルでは、Scalaのインデックスにアクセスしながらコレクションを反復処理する方法を説明します。

2. zipメソッドの使用

Scalaは、反復インデックスにアクセスするためのいくつかの可能性を提供します。 最も単純なソリューションは、 zipメソッドを使用して、元のリストをインデックスを含む別のリストと結合します。 このアプローチを使用すると、インデックスとzipの両方のリストを使用して別のリストを手動で作成できます。

scala> val lst = List("a","b","c","d","e")
val lst: List[String] = List(a, b, c, d, e)

scala> lst.zip(List(0,1,2,3,4,5,6,7)).foreach(println)
(a,0)
(b,1)
(c,2)
(d,3)
(e,4)

zip メソッドは、元のリストを結合するリストを返すことに注意してください。 ただし、両方の要素数が異なる場合、結果のリストは、渡された最小のリストと同じくらい小さくなります。 前の例では、5つの要素を持つリストがありますが、2番目の例には8つの要素があることがわかります。 結果の結合リストにも5つの要素しかなく、長いリストの余分な要素は破棄されます。

3. zipRangeの使用

前は大丈夫な例でした。 しかし、実際には、リストのサイズはわかりません。 Rangesを使用してこれを克服できます。 範囲は通常のリストと同じように繰り返すことができますが、すべての要素をメモリに格納しないという利点があります。を使用してまで範囲を作成できます。方法:

scala> 0 until 5
val res0: scala.collection.immutable.Range = Range 0 until 5

scala> (0 until 5).toList
val res1: List[Int] = List(0, 1, 2, 3, 4)

次に、zipの例で範囲を使用してみましょう。

scala> lst.zip(0 until lst.size).foreach(println)
(a,0)
(b,1)
(c,2)
(d,3)
(e,4)

これで、インデックス付きのリストができました。

4. タプルへのアクセス

お気づきかもしれませんが、.zipメソッドはペアのリストを作成します。 タプルの各部分にアクセスする必要がある場合、Scalaを使用すると非常に簡単にアクセスできます。 元の要素とインデックスの両方にアクセスするzipリストを繰り返し処理してみましょう。 この例では、文字列を出力するだけです。

scala> lst.zip(0 until lst.size).foreach(tuple => println(s"original element: ${tuple._1} => index: ${tuple._2}"))
original element: a => index: 0
original element: b => index: 1
original element: c => index: 2
original element: d => index: 3
original element: e => index: 4

または、さらに良いことに、scala caseステートメントを使用します。

scala> lst.zip(0 until lst.size).foreach{ case (elem, idx) => println(s"original element: ${elem} => index: ${idx}")}
original element: a => index: 0
original element: b => index: 1
original element: c => index: 2
original element: d => index: 3
original element: e => index: 4

5. zipWithIndexを使用する

しかし、これはすべて少し無駄に思えます。 注意深く見ると、インデックスを保持するための2番目のリストを作成しており、3番目のリストに圧縮されています。 この例では問題ありませんが、大きなリストがある場合、このアプローチは大量のメモリ過負荷を表します。さらに、このような一般的な操作には手間がかかりすぎるようです。

Scalaは.zipWithIndexメソッドを使用して、これを行うためのより良い方法を提供します。

scala> lst.zipWithIndex.foreach{ case (elem, idx) => println(s"original element: ${elem} => index: ${idx}")}
original element: a => index: 0
original element: b => index: 1
original element: c => index: 2
original element: d => index: 3
original element: e => index: 4

zipWithIndex メソッドを使用すると、インデックスを保持するためだけに補助リストを作成することを回避できます。 そして、コードははるかにクリーンになりました。

6. 結論

この記事では、Scalaのインデックスにアクセスしながらコレクションを反復処理するためのいくつかのソリューションを見ました。