LoginSignup
19
21

More than 1 year has passed since last update.

【Kotlin備忘録】コレクション関数 map, filter, generateSequence

Last updated at Posted at 2019-06-30

目的

実行環境

  • 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) }
}

distinct()を追加することで、sequence内から重複要素を削除しています。

出力結果(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

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

Qiita

Kotlinlang.org

19
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
21