はじめに
公式の問題集「Kotlin Koans」を解きながらKotlinを学習します。
過去記事はこちら
- Introduction
- Classes
- Conventions
- Collections
問題
Sequences
シーケンスについて学びましょう。
シーケンスは、eagerlyではなくlazilyに操作を実行することを可能にします。
前のタスクの実装をコピーして、シーケンスに対する操作を使用するように変更してください。
修正前コード.kt
// Find the most expensive product among all the delivered products
// ordered by the customer. Use `Order.isDelivered` flag.
fun findMostExpensiveProductBy(customer: Customer): Product? {
TODO()
}
// Count the amount of times a product was ordered.
// Note that a customer may order the same product several times.
fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int {
TODO()
}
fun Customer.getOrderedProducts(): Sequence<Product> =
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
}
問題のポイント
シーケンスを作成するには、引数として要素を列挙してsequenceOf()関数を呼び出します。
val numbersSequence = sequenceOf("four", "three", "two", "one")
Iterable オブジェクト (リストやセットなど) をすでに持っている場合は、asSequence() を呼び出すことでシーケンスを作成することができます。
val numbers = listOf("one", "two", "three", "four")
val numbersSequence = numbers.asSequence()
解答例
// Find the most expensive product among all the delivered products
// ordered by the customer. Use `Order.isDelivered` flag.
fun findMostExpensiveProductBy(customer: Customer): Product? {
return customer
.orders
.asSequence()
.filter(Order::isDelivered)
.flatMap(Order::products)
.maxByOrNull(Product::price)
}
// Count the amount of times a product was ordered.
// Note that a customer may order the same product several times.
fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int {
return customers
.asSequence()
.flatMap(Customer::getOrderedProducts)
.count { it == product }
}
fun Customer.getOrderedProducts(): Sequence<Product> =
orders.asSequence().flatMap(Order::products)
Sequenceを使用しない前のタスクでの解答
fun findMostExpensiveProductBy(customer: Customer): Product? {
return customer
.orders
.filter(Order::isDelivered)
.flatMap(Order::products)
.maxByOrNull(Product::price)
}
fun Shop.getNumberOfTimesProductWasOrdered(product: Product): Int {
return customers
.flatMap(Customer::getOrderedProducts)
.count { it == product }
}
fun Customer.getOrderedProducts(): List<Product> =
orders.flatMap(Order::products)