Caution
お使いのブラウザはJavaScriptが実行できない状態になっております。
当サイトはWebプログラミングの情報サイトの為、
JavaScriptが実行できない環境では正しいコンテンツが提供出来ません。
JavaScriptが実行可能な状態でご閲覧頂くようお願い申し上げます。
リスト — reduce() / fold()
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 の中間結果リストを返します。 |
サンプルコード
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 Item(val name: String, val price: Int, val qty: Int)
val cart = listOf(
Item("りんご", 150, 2),
Item("バナナ", 100, 3),
Item("オレンジ", 200, 1)
)
val total = cart.fold(0) { acc, item -> acc + item.price * item.qty }
println("合計金額: ${total}円") // 800円
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
}
概要
『reduce()』は空リストで例外が発生するため、空の可能性があるリストには『fold()』か『reduceOrNull()』を使います。『fold()』はより汎用的で、初期値の型を変えることで「数値リストをマップに変換する」など異なる型への変換にも使えます。
単純な合計・最大値などには専用のショートハンド(『sum()』『max()』など)の方が簡潔です。『fold()』は複雑な集計処理に使います。
平坦化はリスト — flatMap() / flatten()を、グルーピングはリスト — groupBy() / partition()を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。