[Kotlin]意外と深いsplitメソッドの使い方

replaceメソッドと同じように、splitメソッドもただ単純に「文字列をデリミタで分割する」だけのメソッドではありません。

今回はKotlinのsplitメソッドの仕様を詳しく見ていきましょう。

splitメソッド

fun CharSequence.split(
    vararg delimiters: String,    //Char型でも可
    ignoreCase: Boolean = false,
    limit: Int = 0
): List<String>

まずは基本的な使い方。Stringをデリミタ(区切り文字)で分割し、Listを作ります。

val str = "米津玄師,髭男,back number"

val a = str.split(",")
//[米津玄師, 髭男, back number]

val (a,b,c) = str.split(",")
//複数の変数に同時に代入することも可能。この場合は各々の型はString

for (i in str.split(",")){   //Listなので直接for文で回せる
        println(i)
    }

引数

splitの第一引数は可変長引数です。そのため複数のデリミタを指定できます。

val str = "囁くのよ。私の、ゴーストが"
val a = str.split("、","。")     //普通にカンマ区切りで指定
//[囁くのよ, 私の, ゴーストが]

str.split("、",'。')   //Error String型とChar型の混在は不可

第二引数ignoreCaseは初期値falseで大文字小文字を区別し、trueで無視します。

val str = "ixgXnxoXrXe"

str.split("x")
//[i, gXn, oXrXe]

str.split("x",ignoreCase = true)   //名前付きで指定
//[i, g, n, o, r, e]

第三引数はlimit。ここで指定した要素数になるまで分割。

val str = "l-i-m-i-t"
str.split("-",limit = 3)   //第二引数が無ければ名前付きで指定
//[l, i, m-i-t]           3つの要素に分割される

デリミタが連続する場合

デリミタは基本的に分割後の要素では削除されますが、デリミタが続くような文字列の場合、空文字列としてListの要素となります。

val str = "l---i---m---i---t"
str.split("-")
//[l, , , i, , , m, , , i, , , t]

不要であればremoveAllで、List内の空文字列を指定して削除するなどの処理を加えましょう。

val a = str.split("-").toMutableList()   //MutableListに変換
a.removeAll{it == ""}     //ラムダで指定した条件に一致するものを全て削除
println(a)
//[l, i, m, i, t]

正規表現を使ったsplitメソッド

fun CharSequence.split(
    regex: Regex,     //正規表現を受け取る
    limit: Int = 0
): List<String>

splitも正規表現を引数として受け取ることができます。

val str = "P323r3fSaoiYef872Ci9H3O09P2fua3A2jfS2lmvaS"
val re = """[0-9a-z]+""".toRegex()
str.split(re)
//[P, S, Y, C, H, O, P, A, S, S]

Pattern型を使ったsplitメソッド

fun CharSequence.split(
    regex: Pattern,     //Pattern型を受け取る
    limit: Int = 0
): List<String>

こちらは第一引数の型がPatternになっています。これはjava.util.regex.Patternをインポートすることで使うことができる型で、正規表現をコンパイルしたものです。

上と同じ処理をPattern型を使ってやってみましょう。

import java.util.regex.Pattern     //Patternのインポートが必要

fun main() {
    val str = "P323r3fSaoiYef872Ci9H3O09P2fua3A2jfS2lmvaS"

//Pattern.compileメソッドで正規表現をコンパイル
    val p: Pattern = Pattern.compile("""[0-9a-z]+""")

    val ans = str.split(p)     //Patternオブジェクトでsplit
    println(ans)
}
//[P, S, Y, C, H, O, P, A, S, S]

結果は同じですが、forループなどで何度も正規表現を使用する場合は、先にコンパイルしておいた方が処理が軽くなります。正規表現そのままを渡したとしても、裏ではコンパイル作業が行われているからです。

タイトルとURLをコピーしました