リスト — reduce() / fold()
| 対応: | Kotlin 1.0(2016) |
|---|
Kotlinの『reduce()』は初期値なしでリストを畳み込みます。『fold()』は初期値を指定して畳み込みます。合計・積・文字列結合など、リストの要素を1つの値にまとめる処理に使います。
構文
val numbers = listOf(1, 2, 3, 4, 5)
// reduce — 初期値なし(最初の要素が初期値になります)
val sum = numbers.reduce { acc, n -> acc + n } // 15
// fold — 初期値あり(空リストでも安全)
val sumFold = numbers.fold(0) { acc, n -> acc + n } // 15
val product = numbers.fold(1) { acc, n -> acc * n } // 120
// 右から畳み込みます。
val right = numbers.foldRight(0) { n, acc -> n + acc } // 15
メソッド一覧
| メソッド | 概要 |
|---|---|
| リスト.reduce { acc, v -> } | 左から畳み込みます。初期値はリストの最初の要素です。空リストは例外がスローされます。 |
| リスト.reduceOrNull { acc, v -> } | reduce と同じですが、空リストの場合は null を返します。 |
| リスト.reduceRight { v, acc -> } | 右から畳み込みます(引数の順序に注意)。 |
| リスト.fold(初期値) { acc, v -> } | 左から畳み込みます。初期値を指定できます。 |
| リスト.foldRight(初期値) { v, acc -> } | 右から畳み込みます(引数の順序に注意)。 |
| リスト.runningFold(初期値) { acc, v -> } | 各ステップの中間結果リストを返します(prefixSums など)。 |
| リスト.runningReduce { acc, v -> } | reduce の中間結果リストを返します。 |
サンプルコード
sample_list_reduce_fold.kt
fun main() {
val numbers = listOf(1, 2, 3, 4, 5)
// reduce — 合計(最初の要素が初期値)
val sum = numbers.reduce { acc, n -> acc + n }
println("合計: $sum") // 15
// fold — 初期値を指定します(空リストでも安全)
val product = numbers.fold(1) { acc, n -> acc * n }
println("積: $product") // 120
// fold で文字列を連結します。
val words = listOf("Kotlin", "is", "awesome")
val sentence = words.fold("") { acc, w -> if (acc.isEmpty()) w else "$acc $w" }
println("文章: $sentence") // Kotlin is awesome
println()
// 複雑な fold(合計を計算します)
data class Inspector(val name: String, val caseCount: Int, val crimeCoefficientAvg: Int)
val inspectors = listOf(
Inspector("狡噛慎也", 47, 120),
Inspector("常守朱", 63, 35),
Inspector("宜野座伸元", 52, 55)
)
val total = inspectors.fold(0) { acc, inspector -> acc + inspector.caseCount }
println("担当件数合計: ${total}件") // 162件
println()
// runningFold — 累積和(各ステップの中間値を表示)
val cumulative = numbers.runningFold(0) { acc, n -> acc + n }
println("累積和: $cumulative") // [0, 1, 3, 6, 10, 15]
// runningReduce — 累積最大値
val runMax = numbers.map { it * it }.runningReduce { acc, n -> maxOf(acc, n) }
println("累積最大: $runMax")
println()
// foldRight — 右から処理します(引数の順序に注意)
val reversed = listOf("a", "b", "c").foldRight(mutableListOf()) { elem: String, acc: MutableList<String> ->
acc.add(0, elem)
acc
}
println("反転: $reversed")
// 空リストの安全な処理
val empty = emptyList<Int>()
println("reduceOrNull: ${empty.reduceOrNull { acc, n -> acc + n }}") // null
println("fold: ${empty.fold(0) { acc, n -> acc + n }}") // 0
}
kotlinc list_reduce_fold.kt -include-runtime -d list_reduce_fold.jar java -jar list_reduce_fold.jar 合計: 15 積: 120 文章: Kotlin is awesome 担当件数合計: 162件 累積和: [0, 1, 3, 6, 10, 15] 累積最大: [1, 4, 9, 16, 25] 反転: [a, b, c] reduceOrNull: null fold: 0
概要
『reduce()』は空リストで例外が発生するため、空の可能性があるリストには『fold()』か『reduceOrNull()』を使います。『fold()』はより汎用的で、初期値の型を変えることで「数値リストをマップに変換する」など異なる型への変換にも使えます。
単純な合計・最大値などには専用のショートハンド(『sum()』『max()』など)の方が簡潔です。『fold()』は複雑な集計処理に使います。
平坦化はリスト — flatMap() / flatten()を、グルーピングはリスト — groupBy() / partition()を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。