リスト — groupBy() / partition()
| 対応: | Kotlin 1.0(2016) |
|---|
Kotlinの『groupBy()』はキーセレクターでリストをグループ分けしてMap形式で返します。『partition()』は条件でリストを2つに分割します。データの分類・振り分け処理に使います。
構文
val numbers = listOf(1, 2, 3, 4, 5, 6)
// groupBy — キーでグループ化します。
val grouped = numbers.groupBy { if (it % 2 == 0) "偶数" else "奇数" }
// {"奇数": [1, 3, 5], "偶数": [2, 4, 6]}
// partition — 条件で2つのリストに分割します。
val (evens, odds) = numbers.partition { it % 2 == 0 }
// evens: [2, 4, 6], odds: [1, 3, 5]
メソッド一覧
| メソッド | 概要 |
|---|---|
| リスト.groupBy { キー } | キーセレクターで要素をグループ化した Map<K, List<T>> を返します。 |
| リスト.groupBy({ キー }, { 値変換 }) | キーと値変換を指定してグループ化します。 |
| リスト.groupingBy { キー }.eachCount() | グループごとの件数を Map<K, Int> で返します。 |
| リスト.partition { 条件 } | 条件を満たす要素と満たさない要素の Pair<List, List> を返します。 |
| リスト.chunked(n) | n 個ずつのサブリストに分割します。 |
| リスト.windowed(n) | n 個のスライドウィンドウでサブリストを生成します。 |
サンプルコード
sample_list_groupby_partition.kt
data class Student(val name: String, val grade: String, val score: Int)
fun main() {
val students = listOf(
Student("綾波レイ", "A", 95),
Student("碇シンジ", "B", 75),
Student("惣流アスカ", "A", 88),
Student("葛城ミサト", "C", 62),
Student("渚カヲル", "B", 80),
Student("赤木リツコ", "C", 58)
)
// groupBy — 学年でグループ化します。
val byGrade = students.groupBy { it.grade }
println("=== 学年別 ===")
byGrade.forEach { (grade, list) ->
val names = list.map { it.name }
println("$grade: $names")
}
// 値変換付き groupBy(名前だけグループ化)
val namesByGrade = students.groupBy({ it.grade }, { it.name })
println("\n学年→名前: $namesByGrade")
// グループごとの件数
val countByGrade = students.groupingBy { it.grade }.eachCount()
println("件数: $countByGrade")
println()
// partition — 合格(70点以上)と不合格で分割します。
val (passed, failed) = students.partition { it.score >= 70 }
println("=== 合否 ===")
println("合格: ${passed.map { it.name }}")
println("不合格: ${failed.map { it.name }}")
println()
// chunked — バッチ処理に使います(3件ずつ)
val chunks = students.chunked(3)
println("=== バッチ処理 ===")
chunks.forEachIndexed { i, batch ->
println("バッチ $i: ${batch.map { it.name }}")
}
println()
// windowed — 移動平均などに使います(3件のスライドウィンドウ)
val scores = students.map { it.score }
val windows = scores.windowed(3)
println("=== 3点移動平均 ===")
windows.forEach { w ->
println("$w → 平均: ${"%.1f".format(w.average())}")
}
}
kotlinc list_groupby_partition.kt -include-runtime -d list_groupby_partition.jar
java -jar list_groupby_partition.jar
=== 学年別 ===
A: [綾波レイ, 惣流アスカ]
B: [碇シンジ, 渚カヲル]
C: [葛城ミサト, 赤木リツコ]
学年→名前: {A=[綾波レイ, 惣流アスカ], B=[碇シンジ, 渚カヲル], C=[葛城ミサト, 赤木リツコ]}
件数: {A=2, B=2, C=2}
=== 合否 ===
合格: [綾波レイ, 碇シンジ, 惣流アスカ, 渚カヲル]
不合格: [葛城ミサト, 赤木リツコ]
=== バッチ処理 ===
バッチ 0: [綾波レイ, 碇シンジ, 惣流アスカ]
バッチ 1: [葛城ミサト, 渚カヲル, 赤木リツコ]
=== 3点移動平均 ===
[95, 75, 88] → 平均: 86.0
[75, 88, 62] → 平均: 75.0
[88, 62, 80] → 平均: 76.7
[62, 80, 58] → 平均: 66.7
概要
『groupBy()』はSQLの『GROUP BY』に相当します。返値は『Map<K, List<T>>』なので、各グループに対してさらに集計(『map { it.value.size }』など)が可能です。
『partition()』は2つのグループに分けるシンプルな操作で、分割宣言(『val (a, b) = ...』)を使うとスッキリ書けます。3つ以上に分けたい場合は『groupBy()』を使います。
畳み込み・集計はリスト — reduce() / fold()を、平坦化はリスト — flatMap() / flatten()を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。