[毎日Kotlin] Day26. FlatMap
はじめに
毎日Kotlinシリーズです。
このシリーズを初めての方はこちらです。「毎日Kotlin」はじめました | Developers.IO
問題
Implement Customer.getOrderedProducts() and Shop.getAllOrderedProducts() using flatMap.
val result = listOf("abc", "12").flatMap { it.toList() } result == listOf('a', 'b', 'c', '1', '2')
// Return all products this customer has ordered val Customer.orderedProducts: Set<Product> get() { TODO() } // Return all products that were ordered by at least one customer val Shop.allOrderedProducts: Set<Product> get() { TODO() } 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 }
狙い
ここで考えて欲しい問題の意図はなんだろうか?
コレクションを処理する便利関数はたくさんあるので使って覚えよう。
解答例
val Customer.orderedProducts: Set<Product> get() = orders.flatMap { it.products }.toSet() val Shop.allOrderedProducts: Set<Product> get() = customers.flatMap { it.orderedProducts }.toSet()
今回は拡張プロパティを使っています。Day23 ~ Day25とやっていることは変わりません。変数アクセスっぽく呼べるようにしてるだけです。
flatMapはネストの深い階層を平坦にします。val Customer.orderedProductsのflatMap部分だけのわかりやすい等価コードを書きました。
fun flatMap(customer: Customer): List<Product> { val list = mutableListOf<Product>() for (order in customer.orders) { list.addAll(order.products) } return list }
mapとの差はlistに追加しているときに、addAllかaddの違いです。
fun map(customer: Customer): List<Product> { val list = mutableListOf<Product>() for (order in customer.orders) { list.add(order.products) } return list }
mapとflatMapを比較してみよう。
val list = listOf(listOf("a", "b"), listOf("c", "d"), listOf("e", "f")) list.map { it } // [[a, b], [c, d], [e, f]] list.flatMap { it } //[a, b, c, d, e, f]
あとがき
Day27.でまたお会いしましょう。