guijiu
@guijiu (taka kuwa)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Mapの使い方と関数型プログラミングについて

Q&A

Closed

 Josh Skeen, David Greenhalgh著『Kotlinプログラミング』の章末問題を解いています。模範解答がないので、回答が正しいのかどうかわからないため、ご指導いただければと思います。よりKotlinらしい、より関数型プログラミングらしい答えを求めています。
 問題は次のとおりです。

お題
// マップにあるキーと値を逆転させるflipValues関数をつくれ。
val gradesByStudent = mapOf("Josh" to 4.0, "Alex" to 2.0, "Jane" to 3.0)
    //表示例:{Josh=4.0, Alex=2.0, Jane=3.0}
flipValuesList(gradesByStudent)
    //表示例:{4.0=Josh, 2.0=Alex, 3.0=Jane}
私の回答案
fun main() {
    val gradesByStudent = mapOf("Josh" to 4.0, "Alex" to 2.0, "Jane" to 3.0)
    println(gradesByStudent)

    println("表示例:${flipValues(gradesByStudent)}")

}

// Mapの要素を組み立てなおす方法
fun flipValues(gradesByStudent: Map<String, Double>): Map<Double, String> {
    var flip: MutableMap<Double, String> = mutableMapOf()
    gradesByStudent.forEach { (k, v) ->
        flip.put(v, k)
    }
    return flip
}
0

4Answer

私ならこうしますね。

fun <K, V> flipValues(map: Map<K, V>): Map<V, K> =
    map.asSequence().associate { (k, v) -> v to k }
3Like

Comments

  1. @guijiu

    Questioner

    Map型のコレクションを.asSequence()使って遅延評価コレクションのシーケンス型に変換し、それを.associateを使ってキーと値を入れ替えているのですね。
    https://kotlinlang.org/docs/reference/collection-transformations.html#association
    https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/as-sequence.html
    なおmapと書かれている部分は、引数名で前にあるmap(仮引数名)と後ろのmap(実引数名)が同じであれば、どのような名前(例えばabc)を付けてもよさそうですね。
    ご教示くださいまして、ありがとうございます。

より関数型らしく書くならこうです。

fun flipValues(gradesByStudent: Map<String, Double>): Map<Double, String> {
    return gradesByStudent.asSequence().map { it.value to it.key }.toMap()
}

ここで .map メソッドは Map 型とは無関係なことに注意してください。 map は Kotlin に限らず多くの関数型言語に共通する写像操作で、コレクションの値それぞれに関数を適用した値からなる新しいコレクションを返します。

このコードは gradesByStudentPair オブジェクトのシーケンスに変換し、それぞれのペアのキーと値を反転させたペアからなる新しいシーケンスを作り、それを新しい Map オブジェクトに変換しています。

ちなみに .asSequence() を呼ばなくても結果は同じですが、そうすると処理の途中で全ペアを含むリストを作ってすぐ捨てることになるため、メモリが無駄になるはずです。(Kotlin には詳しくないので不正確かもしれません。)

1Like

Comments

  1. @guijiu

    Questioner

    ご教示ありがとうございます。
    まだまだ関数型(kotlinも含めて)をサクサクっと理解できるようなレベルに達していません。
    明日以降、教えていただいたコードをゆっくりと反芻(はんすう)しようと思います。
    まずはお礼まで。

あんまりよくわかってませんが、こんなことですか?

val flipValues = { 
    gradesByStudent : Map<String, Double>  
        -> gradesByStudent
            .map { it.value to it.key } 
            .toMap()
}
0Like

Comments

  1. @guijiu

    Questioner

    ご教示ありがとうございます。
    ラムダをまだマスターしていないため、教えていただいたコードを明日以降復習を兼ねて、読み解こうと思います。
    まずはお礼まで。

追記。もっとそれっぽいのだと:

val flipValues : (Map<String, Double>) -> Map<Double, String> = { 
            it
            .map { it.value to it.key } 
            .toMap()
}
0Like

Comments

Your answer might help someone💌