Help us understand the problem. What is going on with this article?

【Kotlin備忘録】コレクション関数 map, filter + おまけ(generateSequence)

目的

実行環境

  • Kotlin Playground
  • Kotlin Version 1.4.10 <- 歯車マーク(Setting)からバージョンが確認できます

Map

コレクションの各要素について、加工をした結果をListとして取得します。

サンプルコード1

既存のコレクションで保持している各要素に対して、文字列を付与した新たなコレクションを取得します。

fun main() {

    val fruits = listOf("Strawberry", "Grape", "Orange")

    // fruits の各要素に文字列を追加したListを作成
    val greatFruits = fruits.map {
        "Great $it!" // <- 各要素は"it"として取得できる
    }

    println(fruits)
    println(greatFruits)
}

出力結果

[Strawberry, Grape, Orange]
[Great Strawberry!, Great Grape!, Great Orange!]

サンプルコード2

既存のMapのキーと値を入れ替えた新たなMapを作成する

fun main() {
    val pricesByFruit = mapOf("Strawberry" to 4.5, "Grape" to 5.1, "Orange" to 3.0)

    // 既存のMapのキーと値を入れ替えたMapを作成する
    val fruitByPrice = pricesByFruit.map {
        // pricesByFruitの各要素の値を利用したPairを作成し、Listの1要素として取得
        it.value to it.key
    }.toMap() // <- そのままだとListが戻り値になるため、toMap()でMapに変更する

    println(pricesByFruit)
    println(fruitByPrice)
}

出力結果

{Strawberry=4.5, Grape=5.1, Orange=3.0}
{4.5=Strawberry, 5.1=Grape, 3.0=Orange}

おまけ

サンプルコード2(Mapのキーと値を入れ替える処理)を関数として定義

/**
 * MapのキーとValueを入れ替えたMapを生成する
 * Genericsを利用して、どのような型でも入るようにしている
 * (K = MapKey, V = MapValue を意図している)
 * ※キーになる値が同一の場合、マージされるので注意すること 
 */
fun <K, V> flipValues(sourceMap: Map<K, V>) : Map<V, K> = sourceMap
    .map {
           it.value to it.key
        }
    .toMap()

Filter

コレクションの各要素について、結果に合致するListを取得します。

サンプルコード

コレクションから g G が含まれている要素を抜き出す

fun main() {
    val fruits = listOf("Strawberry", "Grape", "Orange")

    val gFruits = fruits.filter {
        // 要素をすべて小文字にし、大文字小文字関係なく"g"が入っているかをチェック
        it.toLowerCase().contains("g") // <- 各要素は"it"として取得できる
    }

    println(fruits)
    println(gFruits)
}

出力結果

[Strawberry, Grape, Orange]
[Grape, Orange]

コレクションの各要素取得方法について

コレクションの各要素を取得する方法としては、コレクションをループで回して、加工した各要素を変数に代入するという方法もあります。

mapのサンプルコードのループによる代入で書き換えたものが以下です。

fun main() {
    val fruits = listOf("Strawberry", "Grape", "Orange")

    // あらかじめ作成した変数にforEach内で要素を追加する
    val fGreatFruit = mutableListOf<String>()
    fruits.forEach{
        fGreatFruit.add("Great $it!")
    }

    println(fruits)
    println(fGreatFruit)
}

ループにて取得したコードもmapで取得した場合と同じ出力結果が得られますが、以下の点が好ましくないと考えております。

  • 代入先がMutableになる <- 別箇所で変数を利用する際、予期せぬ代入が行われているかもしれない
  • 変数の宣言と代入処理が分離するため、見通しが悪くなりやすい <- 宣言と代入処理が離れる場合がある

おまけ(generateSequence)

複数のリストを組み合わせて1つのコレクションを作る際に、generateSequenceを利用していたため、おまけとしてサンプルコードを残します。

重複要素ありのパターン

fun main() {
    val fruits = listOf("Strawberry", "Grape", "Orange", "Banana", "Apple")
    val adjectives  = listOf("Sour", "Chewy", "Sweet", "Hard", "Soft")

    // 形容詞と果物名を組み合わせた文字列でSequenceオブジェクトを作成する
    val fruitsStr = generateSequence{
        val fruit = fruits.random()
        val adjective = adjectives.random()
        "$adjective $fruit"
    }.take(15) // 15個の要素を取得

    fruitsStr.forEach{ println(it) }
}

出力結果(15個の形容詞付きフルーツ名が表示されている)

Chewy Strawberry
Sour Orange
Hard Orange
Chewy Apple
Sweet Grape
Hard Orange
Hard Apple
Hard Banana
Chewy Apple
Chewy Grape
Chewy Grape
Chewy Orange
Hard Strawberry
Chewy Banana
Soft Orange

上記のように複数のリストの内容を組み合わせた新たなSequenceオブジェクトが取得可能で、その中身をループを利用して取得することが可能です。
※出力結果内にChewy Grapeのように同一要素が2つ入っていることからも分かる通り、取得要素がユニークではありません

重複要素なしのパターン

fun main() {
    val fruits = listOf("Strawberry", "Grape", "Orange", "Banana", "Apple")
    val adjectives  = listOf("Sour", "Chewy", "Sweet", "Hard", "Soft")

    // 形容詞と果物名を組み合わせた文字列でSequenceオブジェクトを作成する
    val fruitsStr = generateSequence{
        val fruit = fruits.random()
        val adjective = adjectives.random()
        "$adjective $fruit"
    }.distinct().take(15) // distinct()で重複を排除し、そこから15個の要素を取得

    fruitsStr.forEach{ println(it) }
}

出力結果(15個の重複なし形容詞付きフルーツ名が表示されている)

Hard Apple
Soft Grape
Sour Orange
Sweet Grape
Sour Apple
Chewy Orange
Chewy Grape
Soft Banana
Hard Strawberry
Hard Orange
Chewy Banana
Hard Banana
Soft Apple
Soft Orange
Sour Strawberry

重複ありの場合とのコードの差はdistinct()を付けるかどうかだけです。
distinct()を付けることによって重複を排除した組み合わせから、take()で指定した分の要素を取得することができます。

参考にさせていただいたURI

Qiita

Kotlinlang.org

watame
主に自分の備忘録を記載しています。間違いなどあれば指摘いただけると嬉しいです!
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away