[AD] Scalaアプリケーションの開発・保守は合同会社ミルクソフトにお任せください
この記事では、Scalaで文字列を分割する方法をご紹介します。
文字列を分割するには、以下の4つの選択肢があります。使い方は以下のとおりです。
split
- 指定した文字で分割します。
splitAt
- 引数に渡したインデックスをもとに分割します。
linesIterator
- 改行文字で区切って文字列をIteratorで返します。各文字列に改行文字は含まれません。
linesWithSeparators
- 改行文字で区切って文字列をIteratorで返します。各文字列に改行文字は含まれます。
それぞれのメソッドの使い方を具体的に見ていきましょう。
splitメソッドの使い方
split
メソッドを使用すると、特定の文字で区切られた文字列を分割することができます。
例えばCSV形式のように、カンマやスペース、タブ文字で区切られた文字列を分割するのに役立ちます。
split
メソッドには4通りの呼び出し方があります。
まず、java.lang.String
に定義されているのがこの2つです。
Javapublic String[] split(String: regexp) public String[] split(String: regexp, Int: limit)
また、scala.collection.StringOps
に定義されているのがこの2つです。
Scaladef split(separator: Char): Array[String] def split(separators: Array[Char]): Array[String]
StringOps
とは、Scalaにおいてjava.lang.String
を便利に使うことができるラッパークラスです。
次に、それぞれのsplit
メソッドを使うサンプルコードを示します。
特定の文字で文字列を分割する
特定の文字によって文字列を分割してみましょう。
文字列を分割する際の区切り文字はChar
型で指定します。
Char
型ではなくString
型、つまり文字列型を指定した場合には、後述の正規表現を引数に取るメソッドを呼び出すことになるので注意してください。
String
型であれば1文字でも文字列型です。ご注意ください。
文字列で指定する方法は後ほど説明します。
次のサンプルでは、文字列をカンマ(,)で分割します。
最後の空文字は省略されます。
val str = "1,2,3,4,5," val result = str.split(',') result.zipWithIndex.foreach { case (s, i) => println(s"[${i}] : ${s}") }
実行結果は以下のようになります。
カンマ(,)で分割すると、"1", "2", "3", "4", "5", ""となりますが、最後の空文字は省略されます。
[0] : 1 [1] : 2 [2] : 3 [3] : 4 [4] : 5
split(separator: Char): Array[String]
文字を複数指定して文字列を分割する
複数の文字で分割する場合は、区切り文字をChar
型の配列で指定します。
次のサンプルでは、文字列をパイプ(|)またはカンマ(,)のいずれかで分割します。
val str = "2019/12/31 00:00:00|1,2,3,4,5|" val result = str.split(Array('|', ',')) result.zipWithIndex.foreach { case (s, i) => println(s"[${i}] : ${s}") }
実行結果は以下のようになります。
パイプの箇所とカンマの箇所のいずれにおいても分割されていることがわかります。
[0] : 2019/12/31 00:00:00 [1] : 1 [2] : 2 [3] : 3 [4] : 4 [5] : 5
split(separators: Array[Char]): Array[String]
文字列を渡すと正規表現で分割する
前述の文字列をパイプ(|)とカンマ(,)で分割する方法は、正規表現で指定することもできます。
パイプ(|)は、正規表現でエスケープが必要な文字なので、バックスラッシュ(\)でエスケープして指定します。
val str = "2019/12/31 00:00:00|1,2,3,4,5|" val result = str.split("\\||,") result.zipWithIndex.foreach { case (s, i) => println(s"[${i}] : ${s}") }
実行結果は、前述の複数のChar
型の値での分割と同様に、以下のようになります。
[0] : 2019/12/31 00:00:00 [1] : 1 [2] : 2 [3] : 3 [4] : 4 [5] : 5
java.lang.String#split(java.lang.String)
分割上限回数を指定して正規表現で分割する
正規表現で分割する方法では、メソッドの第2引数にパターンの適用回数を指定することができます。
0を指定した場合は、省略した場合と同じです。
val str = "2019/12/31 00:00:00|1,2,3,4,5|" val result = str.split("\\||,", 0) result.zipWithIndex.foreach { case (s, i) => println(s"[${i}] : ${s}") }
実行結果
[0] : 2019/12/31 00:00:00 [1] : 1 [2] : 2 [3] : 3 [4] : 4 [5] : 5
マイナスの値を指定した場合は、結果に最後の空文字も含まれます。
val str = "2019/12/31 00:00:00|1,2,3,4,5|" val result = str.split("\\||,", -1) result.zipWithIndex.foreach { case (s, i) => println(s"[${i}] : ${s}") }
実行結果
[0] : 2019/12/31 00:00:00 [1] : 1 [2] : 2 [3] : 3 [4] : 4 [5] : 5 [6] :
3を指定した場合は、以下のように3つに分割されます。
val str = "2019/12/31 00:00:00|1,2,3,4,5|" val result = str.split("\\||,", 3) result.zipWithIndex.foreach { case (s, i) => println(s"[${i}] : ${s}") }
実行結果
[0] : 2019/12/31 00:00:00 [1] : 1 [2] : 2,3,4,5|
java.lang.String#split(java.lang.String, int)
抽出子(Extractor)を使用する
split
は、Array[String]
を返しますが、抽出子(Extractor)を使用することで分割した各要素の値を簡単に取り出すことができます。
val str = "Taro Pedia Scala" val Array(firstName, middleName, lastName) = str.split(' ') println(s"First Name : ${firstName}") println(s"Middle Name : ${middleName}") println(s"Last Name : ${lastName}")
実行結果
First Name : Taro Middle Name : Pedia Last Name : Scala
splitAtメソッドの使い方
splitAt
メソッドは、文字列のインデックスnの位置で分割したものの前半と後半をタプルで返します。
n番目の文字は前半に入ります。
結果は、val (former, latter) = ...
のように受けることで、一度に変数として宣言することができます。
val str = "2019/12/31 00:00:00|1,2,3,4,5" val (former, latter) = str.splitAt(19) println(former) println(latter)
結果は以下のようになります。
2019/12/31 00:00:00 |1,2,3,4,5
splitAt(n: Int): (String, String)
改行文字で区切る方法
linesIteratorメソッドの使い方
linesIterator
メソッドは、文字列を改行文字で区切って、結果をIterator
で返します。
各文字列に改行文字は含まれません。
val str = s"""2019/12/31 00:00:00 1,2,3,4,5 """.stripMargin val result = str.linesIterator result.zipWithIndex.foreach { case (s, i) => println(s"[${i}] : ${s}") }
出力は以下のようになります。
与えた文字列が改行文字によって分割され、1行ずつ処理できているていることがわかります。
出力結果が改行されているのは、println
メソッドが末尾に付加している改行文字によるものです。
[0] : 2019/12/31 00:00:00 [1] : 1,2,3,4,5
linesIterator: Iterator[String]
また、lines
メソッドもlinesIterator
メソッドと同じ働きをします。
ただし、このメソッドはScala 2.13.0で急遽削除されました。
Java 11でString
に追加されたpublic Stream<String> lines()
メソッドと競合してしまったためです。
今後はlinesIterator
を使用し、既存の使用箇所も速やかに置き換えましょう。
lines: Iterator[String]
linesWithSeparatorsメソッドの使い方
linesWithSeparators
メソッドは、文字列を改行文字で区切って、結果をIterator
で返します。
各文字列に改行文字が含まれるのがlinesIterator
メソッドとの違いです。
val str = s"""2019/12/31 00:00:00 1,2,3,4,5""".stripMargin val result = str.linesWithSeparators result.zipWithIndex.foreach { case (s, i) => println(s"[${i}] : ${s}") }
出力は以下のようになります。
結果に改行文字が含まれているので、println
の改行と相まって1行飛ばしで出力されていることがわかります。
[0] : 2019/12/31 00:00:00 [1] : 1,2,3,4,5
linesWithSeparators: Iterator[String]