Secara umum, semua 6 fungsi lipat berlaku operator biner untuk setiap elemen koleksi. Hasil dari setiap langkah diteruskan ke langkah berikutnya (sebagai input ke salah satu dari dua argumen operator biner). Dengan cara ini kita bisa mengumpulkan hasilnya.
reduceLeft dan reduceRight mengumpulkan satu hasil.
foldLeft dan foldRight mengumpulkan satu hasil menggunakan nilai awal.
scanLeft dan scanRight mengumpulkan kumpulan hasil kumulatif antara menggunakan nilai awal.
Mengumpulkan
Dari KIRI dan ke depan ...
Dengan kumpulan elemen abcdan operator biner, addkita dapat menjelajahi apa fungsi lipatan yang berbeda dilakukan saat beralih dari elemen LEFT koleksi (dari A ke C):
val abc = List("A", "B", "C")
def add(res: String, x: String) = {
println(s"op: $res + $x = ${res + x}")
res + x
}
abc.reduceLeft(add)
// op: A + B = AB
// op: AB + C = ABC // accumulates value AB in *first* operator arg `res`
// res: String = ABC
abc.foldLeft("z")(add) // with start value "z"
// op: z + A = zA // initial extra operation
// op: zA + B = zAB
// op: zAB + C = zABC
// res: String = zABC
abc.scanLeft("z")(add)
// op: z + A = zA // same operations as foldLeft above...
// op: zA + B = zAB
// op: zAB + C = zABC
// res: List[String] = List(z, zA, zAB, zABC) // maps intermediate results
Dari KANAN dan mundur ...
Jika kita mulai dengan elemen KANAN dan mundur (dari C ke A) kita akan melihat bahwa sekarang yang kedua argumen ke operator biner kita mengakumulasi hasilnya (operatornya sama, kita hanya mengganti nama argumen untuk memperjelas peran mereka. ):
def add(x: String, res: String) = {
println(s"op: $x + $res = ${x + res}")
x + res
}
abc.reduceRight(add)
// op: B + C = BC
// op: A + BC = ABC // accumulates value BC in *second* operator arg `res`
// res: String = ABC
abc.foldRight("z")(add)
// op: C + z = Cz
// op: B + Cz = BCz
// op: A + BCz = ABCz
// res: String = ABCz
abc.scanRight("z")(add)
// op: C + z = Cz
// op: B + Cz = BCz
// op: A + BCz = ABCz
// res: List[String] = List(ABCz, BCz, Cz, z)
.
De-kumulasi
Dari KIRI dan ke depan ...
Jika sebaliknya kami harus melakukan de-kumulasi beberapa hasil dengan mengurangi mulai dari elemen LEFT koleksi, kami akan mengumpulkan hasil melalui argumen pertama resdari operator biner kami minus:
val xs = List(1, 2, 3, 4)
def minus(res: Int, x: Int) = {
println(s"op: $res - $x = ${res - x}")
res - x
}
xs.reduceLeft(minus)
// op: 1 - 2 = -1
// op: -1 - 3 = -4 // de-cumulates value -1 in *first* operator arg `res`
// op: -4 - 4 = -8
// res: Int = -8
xs.foldLeft(0)(minus)
// op: 0 - 1 = -1
// op: -1 - 2 = -3
// op: -3 - 3 = -6
// op: -6 - 4 = -10
// res: Int = -10
xs.scanLeft(0)(minus)
// op: 0 - 1 = -1
// op: -1 - 2 = -3
// op: -3 - 3 = -6
// op: -6 - 4 = -10
// res: List[Int] = List(0, -1, -3, -6, -10)
Dari KANAN dan mundur ...
Tapi lihat variasi xRight sekarang! Ingat bahwa (de-) nilai terakumulasi dalam variasi xRight diteruskan ke parameter keduares dari operator biner kami minus:
def minus(x: Int, res: Int) = {
println(s"op: $x - $res = ${x - res}")
x - res
}
xs.reduceRight(minus)
// op: 3 - 4 = -1
// op: 2 - -1 = 3 // de-cumulates value -1 in *second* operator arg `res`
// op: 1 - 3 = -2
// res: Int = -2
xs.foldRight(0)(minus)
// op: 4 - 0 = 4
// op: 3 - 4 = -1
// op: 2 - -1 = 3
// op: 1 - 3 = -2
// res: Int = -2
xs.scanRight(0)(minus)
// op: 4 - 0 = 4
// op: 3 - 4 = -1
// op: 2 - -1 = 3
// op: 1 - 3 = -2
// res: List[Int] = List(-2, 3, -1, 4, 0)
Daftar terakhir (-2, 3, -1, 4, 0) mungkin bukan yang Anda harapkan secara intuitif!
Seperti yang Anda lihat, Anda dapat memeriksa apa yang dilakukan foldX Anda dengan hanya menjalankan scanX dan men-debug hasil yang terakumulasi pada setiap langkah.
Intinya