Caution

お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。

Kotlin辞典

  1. トップページ
  2. Kotlin辞典
  3. リスト — flatMap() / flatten()

リスト — flatMap() / flatten()

Kotlinの『flatMap()』は各要素を変換してリストを返し、それを1つのリストに平坦化します。『flatten()』はネストしたリスト(List<List<T>>)を1段階平坦化します。

構文
// flatMap — 変換してから平坦化します。
val words = listOf("hello", "world")
val chars = words.flatMap { it.toList() }
// ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']

// flatten — ネストしたリストを平坦化します。
val nested = listOf(listOf(1, 2), listOf(3, 4), listOf(5))
val flat = nested.flatten()  // [1, 2, 3, 4, 5]

// map + flatten と同等
val same = words.map { it.toList() }.flatten()
メソッド一覧
メソッド概要
リスト.flatMap { v -> リスト }各要素を変換したリストを結合して1つのリストにします。
リスト.flatMapIndexed { i, v -> リスト }インデックスと要素を使って flatMap します。
ネストリスト.flatten()List<List<T>> を List<T> に平坦化します(1段階のみ)。
シーケンス.flatMap { }遅延評価で flatMap を実行します。
サンプルコード
data class Department(val name: String, val members: List<String>)

fun main() {
    // flatten — ネストしたリストを平坦化します。
    val matrix = listOf(
        listOf(1, 2, 3),
        listOf(4, 5, 6),
        listOf(7, 8, 9)
    )
    println("flatten: ${matrix.flatten()}")

    println()

    // flatMap — 部署ごとのメンバーリストを全員リストに変換します。
    val departments = listOf(
        Department("開発", listOf("Alice", "Bob", "Carol")),
        Department("営業", listOf("Dave", "Eve")),
        Department("人事", listOf("Frank"))
    )

    // 全員のリストを作ります。
    val allMembers = departments.flatMap { it.members }
    println("全メンバー: $allMembers")

    // 部署名付きのリストを作ります。
    val withDept = departments.flatMap { dept ->
        dept.members.map { "${dept.name}: $it" }
    }
    withDept.forEach { println(it) }

    println()

    // flatMap で文字の出現頻度を数えます。
    val words = listOf("kotlin", "java", "swift")
    val allChars = words.flatMap { it.toList() }
    println("全文字数: ${allChars.size}")
    val freq = allChars.groupingBy { it }.eachCount().entries.sortedByDescending { it.value }
    println("頻出文字: ${freq.take(3).map { "${it.key}:${it.value}" }}")

    println()

    // flatMapIndexed でインデックスを使います。
    val lines = listOf("AAA", "BB", "CCCC")
    val indexed = lines.flatMapIndexed { lineIdx, line ->
        line.mapIndexed { charIdx, ch -> "[$lineIdx,$charIdx]$ch" }
    }
    println("インデックス付き: $indexed")

    // Nullable な要素を含む場合(flatMapで除去)
    val groups: List<List<Int>?> = listOf(listOf(1, 2), null, listOf(3, 4))
    val flatSafe = groups.filterNotNull().flatten()
    println("null除去後: $flatSafe")
}
概要

『flatMap()』は「1対多の変換をしてから結合する」パターンで多用されます。SQLの『JOIN』や、ツリー構造の葉ノードを全て集めるような処理に適しています。

『flatten()』は1段階しか平坦化しません。2段階以上ネストした場合は複数回の『flatten()』か、再帰処理が必要です。

zip/unzip の組み合わせはリスト — zip() / unzip()を、グルーピングはリスト — groupBy() / partition()を参照してください。

記事の間違いや著作権の侵害等ございましたらお手数ですがまでご連絡頂ければ幸いです。