List — zip() / unzip()
| Since: | Kotlin 1.0(2016) |
|---|
In Kotlin, zip() returns a list of pairs by combining two lists element by element. unzip() splits a list of pairs back into two separate lists. Use these functions for parallel processing of lists or when merging multiple data sequences.
Syntax
val names = listOf("member_a", "member_b", "member_c")
val scores = listOf(85, 72, 91)
// zip — pairs corresponding elements into Pair objects
val zipped = names.zip(scores)
// [Pair("member_a", 85), Pair("member_b", 72), Pair("member_c", 91)]
// zip with transform — applies a custom transformation
val results = names.zip(scores) { name, score -> "$name: $score points" }
// unzip — splits a list of Pairs back into two lists
val (n, s) = zipped.unzip() // restores names and scores
Method List
| Method | Description |
|---|---|
| listA.zip(listB) | Combines two lists into a list of Pairs, truncated to the length of the shorter list. |
| listA.zip(listB) { a, b -> transform } | Zips two lists using a transform lambda. |
| pairList.unzip() | Splits a list of Pair<A, B> into a Pair<List<A>, List<B>>. |
| list.zipWithNext() | Returns a list of pairs of adjacent elements (useful for computing differences). |
| list.zipWithNext { a, b -> } | Transforms adjacent element pairs and returns a list. |
Sample Code
sample_list_zip_unzip.kt
fun main() {
// Basic zip
val names = listOf("member_a", "member_b", "member_c", "member_d")
val scores = listOf(85, 72, 91, 68)
val ages = listOf(20, 20, 24) // truncated to the shorter length (3 items)
val tags = listOf("value_1", "value_2", "value_3", "value_4")
val zipped = names.zip(scores)
println("zip: $zipped")
// zip with transform
val results = names.zip(scores) { name, score ->
"$name: ${score} points (${if (score >= 80) "Pass" else "Fail"})"
}
results.forEach { println(it) }
println()
// Different lengths (truncated to the shorter list)
val nameAge = names.zip(ages)
println("Different length zip: $nameAge") // 3 items
println()
// zip of names and tags
val nameTagPairs = names.zip(tags) { name, tag -> "$name → $tag" }
nameTagPairs.forEach { println(it) }
println()
// unzip — splits Pairs back into two lists
val (nameList, scoreList) = zipped.unzip()
println("Names: $nameList")
println("Scores: $scoreList")
println()
// zipWithNext — creates pairs of adjacent elements (for computing differences)
val temps = listOf(20.0, 22.5, 19.0, 25.0, 23.0)
println("Temperature changes:")
temps.zipWithNext { today, tomorrow ->
val diff = tomorrow - today
val dir = if (diff > 0) "↑" else if (diff < 0) "↓" else "→"
println(" ${today}°C $dir ${tomorrow}°C (${"%.1f".format(diff)})")
}
println()
// Zipping 3 lists (using zip twice)
val first = listOf(1, 2, 3)
val second = listOf("a", "b", "c")
val third = listOf(true, false, true)
val triple = first.zip(second).zip(third) { (a, b), c -> Triple(a, b, c) }
triple.forEach { println(it) }
}
list_zip_unzip.kt
kotlinc list_zip_unzip.kt -include-runtime -d list_zip_unzip.jar java -jar list_zip_unzip.jar zip: [(member_a, 85), (member_b, 72), (member_c, 91), (member_d, 68)] member_a: 85 points (Pass) member_b: 72 points (Fail) member_c: 91 points (Pass) member_d: 68 points (Fail) Different length zip: [(member_a, 20), (member_b, 20), (member_c, 24)] member_a → value_1 member_b → value_2 member_c → value_3 member_d → value_4 Names: [member_a, member_b, member_c, member_d] Scores: [85, 72, 91, 68] Temperature changes: 20.0°C ↑ 22.5°C (2.5) 22.5°C ↓ 19.0°C (-3.5) 19.0°C ↑ 25.0°C (6.0) 25.0°C ↓ 23.0°C (-2.0) (1, a, true) (2, b, false) (3, c, true)
Common Mistakes
The following covers common mistakes related to how zip truncates to the shorter list, unpacking unzip's return value, and replacing manual index loops with zipWithNext.
| Mistake | Cause and Fix |
|---|---|
Assuming zip includes all elements from the longer list | zip truncates to the shorter list with no exception thrown. Extra elements from the longer list are silently dropped. |
Forgetting the return type of unzip | unzip returns Pair<List<A>, List<B>>. Destructuring — val (names, scores) = pairs.unzip() — makes the intent clear. |
Confusing zipWithNext with zip and computing differences manually | zipWithNext pairs each element with its adjacent neighbor in the same list — no second list is needed. It is simpler and more readable than writing index-based loops. |
The sample code below demonstrates the correct usage.
sample_list_zip_unzip_mistakes.kt
fun main() {
val names = listOf("member_a", "member_b", "member_c", "member_d")
val scores = listOf(85, 72, 91)
val zipped = names.zip(scores)
println("zip result count: ${zipped.size}") // 3 (not 4)
println("zip: $zipped")
// Destructuring makes the intent clearer
val unzipped = zipped.unzip()
println("first: ${unzipped.first}") // .first works too
val (nameList, scoreList) = zipped.unzip()
println("Names: $nameList")
println("Scores: $scoreList")
// zipWithNext is more concise than manual index loops
val temps = listOf(20.0, 22.5, 19.0, 25.0)
for (i in 0 until temps.size - 1) {
println("Manual diff: ${temps[i + 1] - temps[i]}")
}
temps.zipWithNext { a, b -> println("zipWithNext diff: ${b - a}") }
}
The command looks like this:
kotlinc sample_list_zip_unzip_mistakes.kt -include-runtime -d sample_list_zip_unzip_mistakes.jar java -jar sample_list_zip_unzip_mistakes.jar zip result count: 3 zip: [(member_a, 85), (member_b, 72), (member_c, 91)] first: [member_a, member_b, member_c] Names: [member_a, member_b, member_c] Scores: [85, 72, 91] Manual diff: 2.5 Manual diff: -3.5 Manual diff: 6.0 zipWithNext diff: 2.5 zipWithNext diff: -3.5 zipWithNext diff: 6.0
Overview
zip() is useful when you want to process two lists in parallel. If the lists have different lengths, the result is truncated to the shorter one — no exception is thrown.
zipWithNext() is useful for computing differences or rates of change between consecutive elements. It replaces index-based for loops.
For flattening lists, see Lists — flatMap() / flatten(). For folding, see Lists — reduce() / fold().
If you find any errors or copyright issues, please contact us.