【Kotlin練習問題】コレクション Association変換

Kotlin

Association変換でMapを作成する

Association(=関連)変換を使うとコレクションの要素と、その要素に関連付けされた特定の値から新たにMapを作成することができます。

Association変換にはいくつか種類があり、使い分けることで要素自体をキーにすることも値にすることもできます。具体的にはassociateWith()associateBy()associate()の3つがあります。それぞれ確認していきましょう。

associateWith()

一番基本の関数はassociateWith()です。これはもとのコレクションの要素がキーとなり、引数に与えられた変換関数によって生成された値がMapの値になります。等しい要素がある場合、最後の要素がMapに残存します。

val numbers = listOf("one", "two", "three", "four")
println(numbers.associateWith { it.length })
//{one=3, two=3, three=5, four=4}

上記コードでは引数に it.length を渡しているので、”one”, “two”, “three”, “four”それぞれの文字列の長さが値になるMapを返します。

associateBy()

もとのコレクションの要素を値とするMapを作るためにはassociateBy()を使用します。

これは要素の値に基づいたキーを返す関数を引数にとり、Mapを作成します。等しい要素がある場合、最後の要素がMapに残存します。

val numbers = listOf("one", "two", "three", "four")
println(numbers.associateBy { it.first().uppercaseChar() })
//{O=one, T=three, F=four}

引数に渡されたit.first().uppercaseChar()は、it.first()でそれぞれの要素の最初の一文字を指定し、uppercaseChar()でそれらを大文字に変換しています。

出力結果ではもとのリストの要素が値になっていることがわかります。

associate()

Another way to build maps in which both keys and values are somehow produced from collection elements is the function associate(). It takes a lambda function that returns a Pair: the key and the value of the corresponding map entry.

キーと値がの両方がなんらかの形でもとのコレクションの要素から生成される場合はassociate()を使います。これは対応するMapのエントリのキーと値のPairを返すラムダ関数を引数にとります。

val names = listOf("Alice Adams", "Brian Brown", "Clara Campbell")
println(names.associate { name -> parseFullName(name).let { it.lastName to it.firstName } })  
//{Adams=Alice, Brown=Brian, Campbell=Clara}

associate()ではこのためだけにPairオブジェクトが生成されるので、パフォーマンスに影響を及ぼす可能性があります。従ってパフォーマンスがそこまで重要視されていないときや、先に説明した二つの関数が使えない場合にのみ、associate()を使うことが推奨されています。

上記コードは少し複雑なので、より分かりやすく使っている例が以下になります。

val list = listOf("abc", "cdef")
print(list.associate { it.first() to it.length } )
//{a=3, c=4}

{キー to 値}の形で指定することができます。

問題

associateBy()、associateWith()、associate()を用いて以下の関数を実装してください。

  1. customerの名前がキー、customerが値のマップを返すnameToCustomerMap()
  2. customerがキー、customerのcityが値のマップを返すcustomerToCityMap()
  3. customerの名前がキー、customerのcityが値のマップを返すcustomerNameToCityMap()

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

問題コード:

//customerの名前がキー、customerが値のマップを返す
fun Shop.nameToCustomerMap(): Map<String, Customer> =
        TODO()

//customerがキー、customerのcityが値のマップを返す
fun Shop.customerToCityMap(): Map<Customer, City> =
        TODO()

//customerの名前がキー、customerのcityが値のマップを返す
fun Shop.customerNameToCityMap(): Map<String, 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
}

答え

//customerの名前がキー、customerが値のマップを返す
fun Shop.nameToCustomerMap(): Map<String, Customer> =
        customers.associateBy { it.name }

//customerがキー、customerのcityが値のマップを返す
fun Shop.customerToCityMap(): Map<Customer, City> =
        customers.associateWith { it.city }

//customerの名前がキー、customerのcityが値のマップを返す
fun Shop.customerNameToCityMap(): Map<String, City> =
    	customers.associate { it.name to it.city }

[解説]

nameToCutomerMap()はキーが元のリストとなるcustomersから生成されたnameなので、associateBy()を使います。

逆にcustomerToCityMap()ではキーがcustomersの要素であるcustomerなので、associateWith()を使います。

customerNameToCityMap()ではキーも値もcustomersから生成されたものを設定したいので、associateを使います。

別解として、customers.associateBy(Customer::name)やcustomers.associateWith(Customer::city)の形にして指定することもできます。

答え

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

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

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

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

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

おすすめ書籍

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

created by Rinker
¥2,640 (2021/10/23 19:13:22時点 Amazon調べ-詳細)

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

プロフィール

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

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

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