Iterable.runningFold în Kotlin

Ca fold, dar întoarce lista cu toate valorile intermediare ale acumulatorului, de exemplu totalurile parțiale.

Sintaxă
fun <T, R> Iterable<T>.runningFold(initial: R, operatie: (acc: R, T) -> R): List<R>
fun <T, R> Iterable<T>.scan(initial: R, operatie: (acc: R, T) -> R): List<R>
fun <T> Iterable<T>.runningReduce(operatie: (acc: T, T) -> T): List<T>

Ce face Iterable.runningFold

runningFold face același calcul ca fold, dar păstrează fiecare pas: lista rezultată începe cu valoarea inițială și conține acumulatorul după fiecare element. O colecție cu n elemente dă o listă cu n + 1 valori.

scan este exact același lucru sub alt nume (numele folosit în alte limbaje). runningReduce pornește de la primul element, fără valoare inițială, deci dă n valori.

Parametri

Parametru Descriere
initial Valoarea de pornire; este primul element al rezultatului.
operatie Primește acumulatorul și elementul curent și întoarce acumulatorul nou.

Ce returnează

O List<R> cu toate valorile acumulatorului, inclusiv cea inițială.

Exemple

Exemplul 1: Soldul după fiecare tranzacție

Primul număr este soldul de pornire, apoi apare soldul după fiecare tranzacție. Ultimul este același cu rezultatul lui fold.

fun main() {
    val tranzactii = listOf(200, -50, -120, 300)
    val solduri = tranzactii.runningFold(100) { acc, t -> acc + t }
    println(solduri)
    println("Final: ${solduri.last()}")
}

Rezultat

[100, 300, 250, 130, 430]
Final: 430

Exemplul 2: scan și runningReduce

scan dă aceeași listă ca runningFold. runningReduce nu are valoare inițială, deci lista are un element mai puțin.

fun main() {
    val kmPeZi = listOf(12, 8, 15, 10)
    println(kmPeZi.scan(0) { acc, km -> acc + km })
    println(kmPeZi.runningReduce { acc, km -> acc + km })
}

Rezultat

[0, 12, 20, 35, 45]
[12, 20, 35, 45]

Exemplul 3: Maximul de până acum

Acumulatorul ține cel mai mare scor văzut până în acel moment. Așa vezi când s-a bătut recordul.

fun main() {
    val scoruri = listOf(40, 55, 50, 70, 65)
    val recorduri = scoruri.runningFold(0) { record, s -> maxOf(record, s) }.drop(1)
    println(recorduri)
}

Rezultat

[40, 55, 55, 70, 70]

Greșeli frecvente

  • Uiți că primul element al rezultatului este valoarea inițială. Dacă vrei doar valorile de după fiecare element, folosește .drop(1) sau runningReduce.

Comenzi înrudite

  • Iterable.fold: Pornește de la o valoare inițială și o combină pe rând cu fiecare element, întorcând rezultatul final.
  • Iterable.reduce: Combină elementele pe rând, pornind de la primul element; nu primește valoare inițială.
  • Iterable.windowed: Întoarce „ferestre” de câte n elemente consecutive care alunecă peste colecție, de exemplu pentru medii mobile.
  • Iterable.take: take(n) întoarce primele n elemente, iar drop(n) întoarce tot ce rămâne după ce sari peste primele n.