Working with Collections
Prerequisites: Collection functions, Data classes
Real programs spend much of their time sorting, grouping, and searching lists of objects. Kotlin's collection functions make this concise.
data class Order(val customer: String, val total: Double, val paid: Boolean)
val orders = listOf(
Order("Ada", 120.0, true),
Order("Linus", 45.0, false),
Order("Ada", 80.0, true),
Order("Grace", 300.0, true),
)
fun main() {
// Sorting by one or more properties
println(orders.sortedByDescending { it.total }.map { it.customer })
println(orders.sortedWith(compareBy({ it.customer }, { it.total })).map { it.total })
// Searching
println(orders.first { !it.paid }.customer)
println(orders.firstOrNull { it.total > 1000 })
println(orders.count { it.paid })
// Grouping and totaling
val spentByCustomer = orders.groupBy { it.customer }
.mapValues { (_, list) -> list.sumOf { it.total } }
println(spentByCustomer)
// Lookup maps
val byCustomer = orders.associateBy { it.customer }
println(byCustomer["Grace"]?.total)
// Largest and smallest by a property
println(orders.maxBy { it.total }.customer)
}
[Grace, Ada, Ada, Linus]
[80.0, 120.0, 300.0, 45.0]
Linus
null
3
{Ada=200.0, Linus=45.0, Grace=300.0}
300.0
Grace
compareBysorts by several properties in turn — here by customer, then by total.groupByreturns a map of lists;mapValuestransforms each list.associateBybuilds a lookup map. If two elements share a key, the last one wins.
Reshaping collections
fun main() {
val names = listOf("Ada", "Linus", "Grace")
val scores = listOf(92, 78, 88)
println(names.zip(scores))
println((1..7).chunked(3))
println((1..5).windowed(2))
println(listOf(listOf(1, 2), listOf(3)).flatten())
println(names.flatMap { name -> name.take(2).toList() })
}
[(Ada, 92), (Linus, 78), (Grace, 88)]
[[1, 2, 3], [4, 5, 6], [7]]
[[1, 2], [2, 3], [3, 4], [4, 5]]
[1, 2, 3]
[A, d, L, i, G, r]
Practice
Using the orders list, print the names of customers with unpaid
orders, and the average total of paid orders.
Show solution
data class Order(val customer: String, val total: Double, val paid: Boolean)
fun main() {
val orders = listOf(
Order("Ada", 120.0, true),
Order("Linus", 45.0, false),
Order("Ada", 80.0, true),
Order("Grace", 300.0, true),
)
println(orders.filterNot { it.paid }.map { it.customer })
println(orders.filter { it.paid }.map { it.total }.average())
}
[Linus]
166.66666666666666