私はKotlinの基本を調べていますが、Kotlinのfold()とreduce()の両方の関数とかなり混同していますが、両方を区別する具体的な例を教えてもらえますか?
fold
は初期値を取り、渡されたラムダの最初の呼び出しはその初期値とコレクションの最初の要素をパラメーターとして受け取ります。
たとえば、整数のリストの合計を計算する次のコードを使用します。
listOf(1, 2, 3).fold(0) { sum, element -> sum + element }
ラムダの最初の呼び出しは、パラメータ0
および1
を使用します。
初期値を渡す機能は、操作に何らかのデフォルト値またはパラメーターを提供する必要がある場合に役立ちます。たとえば、リスト内で最大値を探していて、何らかの理由で少なくとも10を返したい場合、次のようにできます。
listOf(1, 6, 4).fold(10) { max, element ->
if (element > max) element else max
}
reduce
は初期値を取りませんが、代わりにアキュムレーターとしてコレクションの最初の要素から始まります(次の例ではsum
と呼ばれます)。
たとえば、整数の合計をもう一度行いましょう。
listOf(1, 2, 3).reduce { sum, element -> sum + element }
ここでのラムダの最初の呼び出しは、パラメータ1
および2
を使用します。
操作が適用先のコレクションの値以外の値に操作が依存していない場合は、reduce
を使用できます。
私が呼び出す主な機能の違い(他の答えのコメントに記載されていますが、理解するのは難しいかもしれません)は、空のコレクションで実行された場合、reduce
例外をスローしますです。
listOf<Int>().reduce { x, y -> x + y }
// Java.lang.UnsupportedOperationException: Empty collection can't be reduced.
これは、.reduce
が「データなし」のイベントで返す値を知らないためです。
これを.fold
と比較すると、「開始値」を指定する必要があります。これは、空のコレクションが発生した場合のデフォルト値になります。
val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)
したがって、コレクションを集約して、異なる(非関連)タイプの単一要素(.fold
のみで可能)にしたくない場合でも、開始コレクションが空の場合は、最初にコレクションサイズ、次に.reduce
、または単に.fold
を使用します
val collection: List<Int> = // collection of unknown size
val result1 = if (collection.isEmpty()) 0
else collection.reduce { x, y -> x + y }
val result2 = collection.fold(0) { x, y -> x + y }
assertEquals(result1, result2)