Scala スライス関数
今日はScalaのスライス関数を見ていきます。
Scala スライス
Scalaのスライス関数は以下のAPIクラスで利用可能です:
- Scala配列API
- 文字列API
- ScalaコレクションAPI
次のセクションでは、各APIを取り上げ、適切な例を交えて深く議論します。
Scalaのスライス関数の使用
Scala APIでは、'slice'関数は要素の間隔を選択するために使用されます。これは「Int」型の2つのパラメーターを取り、元のコレクション(または文字列または配列)の部分集合、全体、または要素なしを返します。実世界でのスライスのシナリオ:- 以下に示すように、私たちの通常の現実世界の生活でもこのスライス関数を使用できます。
def slice(from-index: Int, until-index: Int): ScalaAPIClass[A]
ここで「ScalaAPIClass」とは、インデックスベースのアクセスをサポートする任意のScalaコレクションクラス(Seq、Listなど)、String、Arrayクラスを意味します。 例: 次の関数はScala APIのSeqクラスで定義されています。
def slice(from-index: Int, until-index: Int): Seq[A]
スライス関数のパラメータ: 「スライス」関数のパラメータの使用法は、以下の表に示されています。
| S.No. | 機能パラメータ | 使用 |
|---|---|---|
| 1. | 最初のパラメータ | 開始インデックス(含む)。それはゼロか、コレクションや文字列や配列の長さ未満の任意の正の整数でなければなりません。 |
| 2. | 第二のパラメータ | 終了インデックス(排他的)。 |
スライス関数は、最初のインデックス(含む)から until-index(除外)までの要素を抽出します。ここで、要素数は数値の配列、文字列の文字、コレクションのオブジェクトです。
Scala配列スライス
Scala APIでは、Arrayクラスはスライス関数を以下のように定義しています:
def slice(from: Int, until: Int): Array[T]
ここで「from」は配列の開始インデックス(含む)で、「until」は配列の終了インデックス(含まない)です。配列スライス関数の例:
scala> val marksArray = Array(56,79,60,99,71)
marksArray: Array[Int] = Array(56, 79, 60, 99, 71)
5つの値を持つ配列の整数が作成されているため、そのインデックスの開始値は0で、インデックスの終了値は4です。長さは5です。それでは、スライス関数で遊んでみましょう。
scala> marksArray.slice(0,2)
res0: Array[Int] = Array(56, 79)
0インデックスから始まり、最初の要素を取得し、2までのすべての要素を取得します。つまり、インデックス=1であるため、ここでは0番目の要素と1番目の要素が得られました。
scala> marksArray.slice(3,4)
res1: Array[Int] = Array(99)
任意のインデックス範囲でアクセスできます。
scala> marksArray.slice(3,3)
res2: Array[Int] = Array()
上記のように開始と終了に同じ値を与えると、なぜ空の配列が得られるのか? 開始インデックス=3 終了インデックス=3 - 1=2 3から2のインデックスの範囲で配列から要素を取得することは不可能だ。
scala> marksArray.slice(-1,3)
res3: Array[Int] = Array(56, 79, 60)
負の値を与えると、上記のように利用可能なインデックスから始まります。
scala> marksArray.slice(0,5)
res4: Array[Int] = Array(56, 79, 60, 99, 71)
上記のように、marksArrayの利用可能な最大インデックス値が4(長さは5なので)である場合、2番目のパラメーター値をそのインデックスを超えて指定すると、その値は無視され、使用可能なインデックスまでの値のみが返されます。注意:Javaとは異なり、ArrayIndexOutOfBoundsExceptionはスローされません。
Scalaコレクションのスライス
Scalaの標準APIでは、ほとんどのクラスがこのスライス関数を定義しており、インデックスベースの要素アクセスをサポートしています。例えば、Listクラスは以下のようにこの関数を定義しています:
def slice(from: Int, until: Int): List[A]
リストスライス関数の例:- 配列の例と同様に、コレクションAPIの任意のもので同じ結果が得られます。
scala> val list = List(56, 79, 60, 99, 71)
list: List[Int] = List(56, 79, 60, 99, 71)
scala> list.slice(0,2)
res5: List[Int] = List(56, 79)
scala> list.slice(3,4)
res6: List[Int] = List(99)
scala> list.slice(3,3)
res7: List[Int] = List()
scala> list.slice(-1,3)
res8: List[Int] = List(56, 79, 60)
scala> list.slice(0,5)
res9: List[Int] = List(56, 79, 60, 99, 71)
空のリストにアクセスすると、以下のように空のリストだけが得られます。
scala> val list2 = List()
list2: List[Nothing] = List()
scala> list2.slice(0,1)
res10: List[Nothing] = List()
Scalaの文字列スライス
Scala APIでは、「StringOps」クラスはscala.collection.immutableパッケージで定義されています。以下に示すように、スライス関数を定義しています:
def slice(from: Int, until: Int): String
注:- ScalaではJavaのStringクラスを使用します。しかし、このクラスにはスライス関数がありません。JavaのStringオブジェクトでスライス関数を使用すると、Scalaコンパイラが内部的にこのStringオブジェクトをStringOpsクラスオブジェクトに変換してスライス関数を使用します。(スライス関数だけでなく、他にも多くあります。詳細についてはScala APIを参照してください。)つまり、「StringOps」はStringクラスの暗黙のクラスです。 Stringスライス関数の例:-
scala> val str = "Hello I'm doing good. How are you?"
str: String = Hello I'm doing good. How are you?
scala> str.slice(6,9)
res8: String = I'm
ご存知のように、文字列のインデックスはゼロから始まります。ここで from-index=6 は until-index=9 を意味します(これは排他的なので、インデックス=8 まで考慮する必要があります)。文字列のサブストリング関数は、以下のようにスライス関数と同じように機能します:
scala> str.substring(6,9)
res12: String = I'm
ここでは、str.slice(6,9)とstr.substring(6,9)が同じ値を返しています。sliceとsubstring Stringクラスのsliceとsubstring関数の違い
- 機能的にも文法的にも違いはありません。
- パフォーマンスはほぼ同じで無視できる。
注: Scalaでは、以下のように文字列の文字に配列の要素のようにアクセスできます:
scala> str(0)
res0: Char = H
ここでは文字が返されますが、文字列は返されません。
scala> str(-1)
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.charAt(String.java:658)
at scala.collection.immutable.StringOps$.apply$extension(StringOps.scala:38)
... 33 elided
scala> str.length
res2: Int = 34
scala> str(34)
java.lang.StringIndexOutOfBoundsException: String index out of range: 34
at java.lang.String.charAt(String.java:658)
at scala.collection.immutable.StringOps$.apply$extension(StringOps.scala:38)
... 33 elided
注意:範囲外の文字にアクセスしようとすると、上記のようにStringIndexOutOfBoundsExceptionが発生します。Stringの文字アクセスはCharを返しますが、substringおよびslice関数は下記のようにStringを返します。
scala> str(0)
res4: Char = H
scala> str.substring(0,1)
res5: String = H
scala> str.slice(0,1)
res6: String = H
それが「Scalaのスライス関数」の使い方です。今後の投稿でさらにいくつかのScalaの概念についてお話しします。参考文献:Scala APIドキュメント

