前書き
この記事を投稿するまでにだいぶ時間が空いてしまいましたが、Kotlin Fest 2019 に参加してきました。
いくつか講演を聞く中で、Kotlin について慣れるまではなかなか Kotlin らしい書き方をするのは難しいかもしれないが、kotlin.text パッケージの機能を使ってみたりすると良いのではないかというのがありました(要約にして意訳)
そこでほぼ公式からの写経になってしまいますが、いくつか試して理解を進めたものを残しておきます。
コードはAndroid StudioのREPL(Kotlin version 1.3.31)で確認しております。
all
inline fun CharSequence.all(
predicate: (Char) -> Boolean
): Boolean
すべての文字が指定されたpredicateと一致するかどうかを返します。
// CharRange型に abc を格納します
val range_a_c = 'a'..'c'
// 引数で渡された文字が range_a_c に含まれていたら true を返す predicate
val isInRange: (Char) -> Boolean = { it in range_a_c }
val alphabet_a_g = "abcdefg"
println("alphabet_a_g.all { isInRange(it) } is ${alphabet_a_g.all { isInRange(it) }}") // false
val alphabet_a_c = "abc"
println("alphabet_a_c.all { isInRange(it) } is ${alphabet_a_c.all { isInRange(it) }}") // true
isLetter
いきなりなんか普通っぽいセレクトになりましたが次で使うため(笑)
fun Char.isLetter(): Boolean
文字であるかどうかを返却します。
val chars = listOf('a', 'あ', '&', '9')
// partition を用いて、isLetter() により、文字とそうでないものを分ける
val (letters, notLetters) = chars.partition { it.isLetter() }
println(letters) // [a, あ]
println(notLetters) // [&, 9]
##takeなんちゃら4種
fun CharSequence.take(n: Int): CharSequence
文字列の先頭からn文字を返却します。
nより文字列が短い場合は文字列全体を返却します。
fun CharSequence.takeLast(n: Int): CharSequence
文字列の最後からn文字を返却します。
nより文字列が短い場合は文字列全体を返却します。
inline fun CharSequence.takeWhile(
predicate: (Char) -> Boolean
): CharSequence
文字列から指定された predicate を満たす最初の文字列を返却します。
inline fun CharSequence.takeLastWhile(
predicate: (Char) -> Boolean
): CharSequence
文字列から指定された predicate を満たす最後の文字列を返却します。
val string = "+++ *** TAKE &&& SAMPLE >>>"
println(string.take(12)) //+++ *** TAKE
println(string.takeLast(10)) //SAMPLE >>>
println(string.takeWhile { !it.isLetter() }) //+++ ***
println(string.takeLastWhile { !it.isLetter() }) // >>>
##zip
指定された変換関数 (transform) を文字の各ペアに適用して、このインデックスと同じインデックスを持つ他の文字列 (other) から構築された値のリストを返します。返されるリストは、最短の文字列の長さとなります。
inline fun <V> CharSequence.zip(
other: CharSequence,
transform: (a: Char, b: Char) -> V
): List<V>
val stringA = "abcd"
val stringB = "zyx"
// {} 内が transform にあたるラムダ式
val result = stringA.zip(stringB) { a, b -> "$a$b" }
// stringBのほうが短いため、stringBの長さの配列が返却される
println(result) // [az, by, cx]
##chunked
fun <R> CharSequence.chunked(
size: Int,
transform: (CharSequence) -> R
): List<R>
文字列を、指定されたサイズを超えない複数の文字列に分割し、指定された transform をそれぞれに適用した結果の配列を返却します。
val table = mapOf("MLB" to "Baseball", "NFL" to "Football", "NBA" to "Basketball", "NHL" to "Hockey", "QB" to "quarterback")
val concatenated = "MLBNHLNFLMLSNBAQB"
// concatenated を 3文字ずつに分けて、transform を適用する
// 最後は3文字に満たない範囲で分割する
// table に無い場合は、"Unknown" とする
val results = concatenated.chunked(3) {
abbreviation: CharSequence -> table[abbreviation.toString()] ?: "Unknown" }
println(results) // [Baseball, Hockey, Football, Unknown, Basketball, quarterback]
後書き
正直な話、Qiita投稿練習用の記事ではありましたが、Kotlinの基礎的なところを見直す機会となりました。
「それでも少しは目新しいものを」とか欲を出したせいで、
普通にアプリを作る上では、使いどころに困るものも選んでしまった感があります。