[毎日Kotlin] Day26. FlatMap

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

毎日Kotlinシリーズです。

このシリーズを初めての方はこちらです。「毎日Kotlin」はじめました | Developers.IO

問題

FlatMap | Try Kotlin

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に追加しているときに、addAlladdの違いです。

fun map(customer: Customer): List<Product> {
    val list = mutableListOf<Product>()
    for (order in customer.orders) {
        list.add(order.products)
    }
    return list
}

mapflatMapを比較してみよう。

    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.でまたお会いしましょう。