Iterable.zip în Kotlin

zip pune față în față elementele a două colecții, pe aceeași poziție; unzip desparte o listă de perechi în două liste.

Sintaxă
infix fun <T, R> Iterable<T>.zip(alta: Iterable<R>): List<Pair<T, R>>
fun <T, R, V> Iterable<T>.zip(alta: Iterable<R>, transformare: (T, R) -> V): List<V>
fun <T, R> Iterable<Pair<T, R>>.unzip(): Pair<List<T>, List<R>>
fun <T> Iterable<T>.zipWithNext(): List<Pair<T, T>>

Ce face Iterable.zip

a.zip(b) formează perechi din elementele de pe aceeași poziție: primul cu primul, al doilea cu al doilea etc. Dacă listele au lungimi diferite, rezultatul are lungimea celei mai scurte; elementele în plus se ignoră. Se poate scrie și infix: a zip b.

Cu o funcție de transformare, zip nu mai creează perechi, ci aplică direct funcția pe cele două elemente (de exemplu le adună).

unzip() face invers: dintr-o listă de perechi obține o pereche de liste, una cu primele componente și una cu a doua. zipWithNext() pune fiecare element lângă următorul din aceeași listă.

Parametri

Parametru Descriere
alta A doua colecție.
transformare Opțional: funcția care combină cele două elemente de pe aceeași poziție.

Ce returnează

zip: o listă de perechi sau de rezultate. unzip: o pereche de liste.

Exemple

Exemplul 1: Nume și note din două liste

Perechile se desfac direct în bucla for. Lista de note are un element în plus, care se ignoră.

fun main() {
    val nume = listOf("Ana", "Ion", "Maria")
    val note = listOf(9, 7, 10, 8)
    for ((elev, nota) in nume zip note) {
        println("$elev: $nota")
    }
}

Rezultat

Ana: 9
Ion: 7
Maria: 10

Exemplul 2: zip cu transformare

Adunăm punctele din cele două probe, pe poziții. Rezultatul este direct o listă de totaluri.

fun main() {
    val scris = listOf(40, 35, 48)
    val oral = listOf(45, 38, 50)
    val total = scris.zip(oral) { s, o -> s + o }
    println(total)
}

Rezultat

[85, 73, 98]

Exemplul 3: unzip și zipWithNext

unzip separă orașele de distanțe. zipWithNext leagă fiecare oraș de următorul, pentru un traseu.

fun main() {
    val etape = listOf("Iași" to 0, "Suceava" to 145, "Cluj" to 320)
    val (orase, km) = etape.unzip()
    println(orase)
    println(km)

    orase.zipWithNext().forEach { (de, la) -> println("$de -> $la") }
}

Rezultat

[Iași, Suceava, Cluj]
[0, 145, 320]
Iași -> Suceava
Suceava -> Cluj

Greșeli frecvente

  • Aștepți o eroare când listele au lungimi diferite: zip taie tăcut la lungimea celei scurte. Verifică lungimile dacă e important.
  • Folosești indici (for (i in a.indices) a[i] + b[i]) și primești IndexOutOfBoundsException când b e mai scurtă: zip evită problema.

Comenzi înrudite

  • Pair: O pereche de două valori, first și second; a to b este felul scurt de a crea un Pair, folosit în mapOf.
  • Iterable.windowed: Întoarce „ferestre” de câte n elemente consecutive care alunecă peste colecție, de exemplu pentru medii mobile.
  • Iterable.associate: Construiește un map din colecție: pentru fiecare element lambda întoarce o pereche cheie to valoare.
  • Iterable.withIndex: Pune lângă fiecare element poziția lui, ca perechi (index, valoare), utile în bucle for.
  • Iterable.flatMap: flatten unește o listă de liste într-o singură listă; flatMap transformă fiecare element într-o listă și le unește.