Iterable.windowed în Kotlin

Întoarce „ferestre” de câte n elemente consecutive care alunecă peste colecție, de exemplu pentru medii mobile.

Sintaxă
fun <T> Iterable<T>.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false): List<List<T>>
fun <T, R> Iterable<T>.windowed(size: Int, step: Int = 1, partialWindows: Boolean = false, transform: (List<T>) -> R): List<R>

Ce face Iterable.windowed

windowed(n) ia primele n elemente, apoi se mută cu un pas (implicit 1) și ia iar n elemente, și tot așa. Ferestrele se suprapun: din [1, 2, 3, 4] cu mărimea 2 obții [1, 2], [2, 3], [3, 4].

Parametrul step (pasul) spune cu câte poziții se mută fereastra. partialWindows = true păstrează și ferestrele de la final care au mai puține elemente. windowed(n, n, true) este același lucru ca chunked(n).

Cu funcția de transformare calculezi direct ceva pe fiecare fereastră, de exemplu media ei.

Parametri

Parametru Descriere
size Câte elemente are fereastra.
step Cu câte poziții se mută fereastra; implicit 1.
partialWindows Dacă se păstrează ferestrele incomplete de la final; implicit false.
transform Opțional: funcția aplicată fiecărei ferestre.

Ce returnează

O listă de ferestre (List<List<T>>) sau de rezultate ale transformării.

Exemple

Exemplul 1: Media pe 3 zile a temperaturilor

Fiecare fereastră are 3 zile consecutive; media lor netezește variațiile. Din 6 zile obținem 4 medii.

fun main() {
    val grade = listOf(12, 15, 18, 14, 20, 22)
    println(grade.windowed(3))
    println(grade.windowed(3) { it.average() })
}

Rezultat

[[12, 15, 18], [15, 18, 14], [18, 14, 20], [14, 20, 22]]
[15.0, 15.666666666666666, 17.333333333333332, 18.666666666666668]

Exemplul 2: Diferența de la o zi la alta

Ferestre de câte 2: al doilea element minus primul arată cât a crescut sau a scăzut prețul.

fun main() {
    val pretPaine = listOf(4, 4, 5, 5, 6, 5)
    val diferente = pretPaine.windowed(2) { it[1] - it[0] }
    println(diferente)
    println("Zile cu scumpire: ${diferente.count { it > 0 }}")
}

Rezultat

[0, 1, 0, 1, -1]
Zile cu scumpire: 2

Exemplul 3: Pas și ferestre parțiale

Cu pasul 2, ferestrele încep la elementele 1, 3 și 5. Fără partialWindows, fereastra incompletă [5] se pierde.

fun main() {
    val numere = listOf(1, 2, 3, 4, 5)
    println(numere.windowed(size = 2, step = 2))
    println(numere.windowed(size = 2, step = 2, partialWindows = true))
}

Rezultat

[[1, 2], [3, 4]]
[[1, 2], [3, 4], [5]]

Greșeli frecvente

  • Confunzi windowed cu chunked: windowed(3) dă ferestre suprapuse, chunked(3) bucăți separate.
  • Colecția are mai puține elemente decât mărimea ferestrei: rezultatul este o listă goală (dacă nu ceri ferestre parțiale).

Comenzi înrudite

  • Iterable.chunked: Împarte colecția în bucăți consecutive de câte n elemente; ultima bucată poate fi mai mică.
  • Iterable.zip: zip pune față în față elementele a două colecții, pe aceeași poziție; unzip desparte o listă de perechi în două liste.
  • Iterable.runningFold: Ca fold, dar întoarce lista cu toate valorile intermediare ale acumulatorului, de exemplu totalurile parțiale.
  • Iterable.average: Calculează media aritmetică a numerelor din colecție; întoarce mereu un Double.