スカラのスライス関数を日本語で言い換えると:「スカラのスライス機能」
今日は、Scalaのslice関数について見てみましょう。
スカラスライス
以下のAPIクラスには、Scalaのスライス関数が利用可能です。
- Scala Array API
- String API
- Scala Collection API
次のセクションでは、各APIを取り上げ、適切な例を使って詳しく議論します。
スカラのスライス関数の使用方法は:
def slice(from-index: Int, until-index: Int): ScalaAPIClass[A]
ここでの「ScalaAPIClass」は、SeqやListなどのインデックスベースのアクセスをサポートしている任意のScalaコレクションクラス、String、Arrayクラスを指します。例:以下の関数はScala APIのSeqクラスに定義されています。
def slice(from-index: Int, until-index: Int): Seq[A]
スライス関数のパラメーター: 「スライス」関数のパラメーターの使用方法は、以下の表に記載されています。
S.No. | Function Params | Usage |
---|---|---|
1. | First Parameter | Starting index (Inclusive). It should be zero or any any positive integer less than the length of the Collection or String or Array. |
2. | Second Parameter | Ending index (Exclusive). |
「スライス」関数は、要素の抽出を行います。最初のインデックス(含む)から、指定したインデックスまで(含まず)の要素が抽出されます。抽出の対象は、数値の配列、文字列の文字、コレクションのオブジェクトです。
スカラのアレイスライスを日本語で言い換えると「スカラ配列の一部分」です。
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)
上記の例で、利用可能なインデックスを超えて2番目のパラメーターの値を指定した場合(marksArrayの利用可能な最大インデックスは5で、長さは5であるため)、その値は無視され、利用可能なインデックスまでの結果のみが返されます。注意:Javaとは異なり、ArrayIndexOutOfBoundsExceptionは発生しません。
スカラコレクションのスライス
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のStringの一部を切り取る
Scala APIでは、「StringOps」というクラスがscala.collection.immutableパッケージに定義されています。以下に示すように、それはスライス機能を定義しています。
def slice(from: Int, until: Int): String
注意:Scalaでは、JavaのStringクラスを使用します。しかし、このクラスにはslice関数はありません。JavaのStringオブジェクトでslice関数を使用する場合、Scalaのコンパイラは内部でこのStringオブジェクトをStringOpsクラスオブジェクトに変換してからこのslice関数を使用します(slice関数だけでなく、他にも多くの機能があります。詳細はScala APIを参照してください)。つまり、「StringOps」はStringクラスの暗黙のクラスです。Stringのslice関数の例:
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 までを考慮する必要があります)。文字列の substring 関数は、以下に示すように slice 関数と同様に機能します。
scala> str.substring(6,9)
res12: String = I'm
ここでは、str.slice(6,9)とstr.substring(6,9)は同じ値を返しています。Stringクラスのsliceとsubstring関数の違い
- Functionality wise and syntax wise there is no difference
- Performance is almost similar and ignorable.
Scalaでは、以下に示すように、Stringの文字には配列要素と同じようにアクセスできます。
scala> str(0)
res0: Char = H
Charを返しますが、Stringではありません。
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が発生します。文字列の文字へのアクセスは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 Doc