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 abc
dan operator biner, add
kita 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 res
dari 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