【Kotlin練習問題】コレクション:マップ(Map)変換の使い方

Kotlin

マップ(Map)とは

Kotlinスタンダードライブラリにはコレクションを変換するための拡張関数のセットが用意されています。これらの関数は指定された変換ルールに従って既存のコレクションから新しいコレクションを生成します。このページではその一つであるマップ(Map)について解説していきます。


マッピング変換ではあるコレクションの要素に対して使われた関数の結果から新しいコレクションが生成されます。基本的なマッピング関数はmap()です。

map()は与えられたラムダ関数を後続の要素に適用し、そのラムダの結果のリストを返します。

結果の順番はもともとの要素の順番と同じです。引数として要素のインデックス番号を使う変換を適用する場合は、mapIndexed()を使います。使用例を見てみましょう。

val numbers = setOf(1, 2, 3)
println(numbers.map { it * 3 }) //[3, 6, 9]
println(numbers.mapIndexed { idx, value -> value * idx }) //[0, 2, 6]

上記コードでは it * 3の部分とidx, value -> value * idxの部分がラムダ関数で、itはnumbersに含まれるそれぞれの要素を意味します。

またidxとvalueはそれぞれインデックス番号とその値(要素)を意味しており、一つ目はインデックス番号が0,値が1なので、返される値は0 * 1(=0)になります。同様に1 * 2、2 * 3と続きます。

もし変換の結果、nullが要素に含まれる場合、map()の代わりにmapNotNull()関数を使うことで、返されるコレクションからnullを取り除くことができます。mapIndexed()に対してはmapIndexedNotNull()が使えます。

val numbers = setOf(1, 2, 3)
println(numbers.mapNotNull { if ( it == 2) null else it * 3 }) //[3, 9]
println(numbers.mapIndexedNotNull { idx, value -> if (idx == 0) null else value * idx }) //[2, 6]

mapを変換する場合、2つの方法があります。一つは値を変更せずにキーのみを変換する方法と、キーを変更せずに値のみを変換する方法です。

与えられた変換ルールをキーに適用したい場合はmapKeys()を使います。値の場合はmapValues()になります。

これらの関数は両方ともmapをマップエントリー(Mapに保持されたキーと値のペアのこと)を引数にとる変換を使っているので、キーと値の両方とも処理することができます。

val numbersMap = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key11" to 11)
println(numbersMap.mapKeys { it.key.uppercase() }) //{KEY1=1, KEY2=2, KEY3=3, KEY11=11}
println(numbersMap.mapValues { it.value + it.key.length }) //{key1=5, key2=6, key3=7, key11=16}

いかがでしたか?今回はマッピング変換について簡単に解説しました。
最後に確認問題を解いてみましょう。

問題

map()を用いて全ての顧客(customer)の出身地(city)を取得する拡張関数を実装してください。

なお、Shopクラスと全ての関連するクラスはShop.ktに含まれています。

問題コード:

//顧客の出身地を取得する
fun Shop.getCustomerCities(): Set<City> =
        TODO()

Shop.kt

data class Shop(val name: String, val customers: List<Customer>)
​
data class Customer(val name: String, val city: City, val orders: List<Order>) {
    override fun toString() = "$name from ${city.name}"
}
​
data class Order(val products: List<Product>, val isDelivered: Boolean)
​
data class Product(val name: String, val price: Double) {
    override fun toString() = "'$name' for $price"
}
​
data class City(val name: String) {
    override fun toString() = name
}

答え

fun Shop.getCustomerCities(): Set<City> =
        customers.map {it.city}.toSet()

[解説]

mapを用いてShopに含まれるcustomers(List型)をcityのリストに変換しています。ただし、返り値はSet型にしなければいけないので、最後にtoSet()をつけてListからSetに変換するのを忘れないようにしましょう。

答え

その他の問題はこちらからどうぞ。

完全無料で通えるプログラミングスクール

プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。

効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。

中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!

おすすめ書籍

Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。

実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。

プロフィール

プロフィール
コードラボJP

大学卒業後SEに就職、現在は退職しフリーランスとして活動中。
『初心者でも挫折せずに一人でプログラミングを学べる』をモットーに、コードラボJPを開設
お問い合わせ等はcodelabsjp@gmail.comまで

コードラボJPをフォローする
タイトルとURLをコピーしました