はじめに
公式の問題集「Kotlin Koans」を解きながらKotlinを学習します。
過去記事はこちら
- Introduction
- Classes
- Conventions
- Collections
問題
Partitionと、partitionと一緒によく使われるDestructuring declarationsの構文について学びましょう。
未納品が納品済みより多い顧客を返却する機能をpartitionで実装します。
修正前コード.kt
// Return customers who have more undelivered orders than delivered
fun Shop.getCustomersWithMoreUndeliveredOrders(): Set<Customer> = TODO()
Shop.kt
data class Shop(val name: String, val customers: List<Customer>)
data class Customer(val name: String, val city: City, val orders: List<Order>) {
override fun toString() = "$name from ${city.name}"
}
data class Order(val products: List<Product>, val isDelivered: Boolean)
data class Product(val name: String, val price: Double) {
override fun toString() = "'$name' for $price"
}
data class City(val name: String) {
override fun toString() = name
}
問題のポイント
Destructuring declarations
オブジェクトをいくつかの変数に分解しておくと便利なことがあります。
この構文を「destructuring declaration」と呼びます。destructuring declarationは、一度に複数の変数を作成します。nameとageという2つの新しい変数を宣言し、それぞれを独立して使えるようにします。
val (name, age) = person
Partition
フィルタリング関数である partition() は、述語によってコレクションをフィルタリングし、それにマッチしない要素を別のリストに保持します。
最初のリストには述語にマッチする要素が、2番目のリストにはそれ以外の要素が含まれています。
// 文字列の長さが3より大きい場合とそれ以外を分ける
val numbers = listOf("one", "two", "three", "four")
val (match, rest) = numbers.partition { it.length > 3 }
println(match) // [three, four]
println(rest) // [one, two]
val numbers = listOf(1, 3, -4, 2, -11)
val (positive, negative) = numbers.partition { it > 0 }
positive == listOf(1, 3, 2)
negative == listOf(-4, -11)
解答例
// 未納品が納品済みより多い顧客を返却する
fun Shop.getCustomersWithMoreUndeliveredOrders(): Set<Customer> =
customers.filter {
val (delivered, undelivered) = it.orders.partition { it.isDelivered }
undelivered.size > delivered.size
}.toSet()