kotlin 中 flatMap 与 map 的用例是什么

What is the use case for flatMap vs map in kotlin

https://try.kotlinlang.org/#/Kotlin%20Koans/Collections/FlatMap/Task.kt

它有使用 flatMapmap

的示例

似乎两者都在做同样的事情,是否有示例显示使用 flatMapmap 的区别?

数据类型:

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
}

样品:

fun Shop.getCitiesCustomersAreFrom(): Set<City> =
    customers.map { it.city }.toSet()
    // would it be same with customers.flatMap { it.city }.toSet() ?

val Customer.orderedProducts: Set<Product> get() {
    return orders.flatMap { it.products }.toSet()
    // would it be same with return orders.map { it.products }.toSet()
}

考虑以下示例:您有一个简单的数据结构 Data,其中包含 List.

类型的单个 属性
class Data(val items : List<String>)

val dataObjects = listOf(
    Data(listOf("a", "b", "c")), 
    Data(listOf("1", "2", "3"))
)

flatMap 对比 map

使用 flatMap,您可以 "flatten" 多个 Data::items 到一个集合中,如 items 变量所示。

val items: List<String> = dataObjects
    .flatMap { it.items } //[a, b, c, 1, 2, 3]

另一方面,使用 map 只会产生一个列表列表。

val items2: List<List<String>> = dataObjects
    .map { it.items } //[[a, b, c], [1, 2, 3]] 

flatten

Iterable<Iterable<T>>Array<Array<T>> 上还有一个 flatten 扩展名,您可以在使用这些类型时替代 flatMap 使用:

val nestedCollections: List<Int> = 
    listOf(listOf(1,2,3), listOf(5,4,3))
        .flatten() //[1, 2, 3, 5, 4, 3]

这里使用了三个函数。 map()flatten()flatMap(),这是前两者的组合.

考虑以下示例

data class Hero (val name:String)
data class Universe (val heroes: List<Hero>)

val batman = Hero("Bruce Wayne")
val wonderWoman = Hero (name = "Diana Prince")

val mailMan = Hero("Stan Lee")
val deadPool = Hero("Wade Winston Wilson")

val marvel = Universe(listOf(mailMan, deadPool))
val dc = Universe(listOf(batman, wonderWoman))

val allHeroes: List<Universe> = listOf(marvel, dc)

地图

allHeroes.map { it.heroes }
// output: [[Hero(name=Stan Lee), Hero(name=Wade Winston Wilson)], [Hero(name=Bruce Wayne), Hero(name=Diana Prince)]]

地图允许您访问{allHeroes}中的每个宇宙和(在本例中)return 它的英雄名单。所以输出将是一个包含两个英雄列表的列表, 每个宇宙一个。 结果是一个列表>

平面图

allHeroes.flatMap { it.heroes } 
// output: [Hero(name=Stan Lee), Hero(name=Wade Winston Wilson), Hero(name=Bruce Wayne), Hero(name=Diana Prince)]

FlatMap 允许你做和 map 一样的事情,访问两个英雄列表 两个宇宙。但它更进一步,使 returned 列表列表变平 成一个列表。 结果是一个列表

展平

allHeroes.map { it.heroes }.flatten() 
// output: [Hero(name=Stan Lee), Hero(name=Wade Winston Wilson), Hero(name=Bruce Wayne), Hero(name=Diana Prince)]

这产生与 flatMap 相同的结果。 所以 flatMap 是两个函数的组合,map{} 和 flatten()

  • Map用于根据一定的条件对列表进行变换(Map帮助我们对列表的每一个元素进行一定的变换,它returns新转换数据的列表)。
  • FlatMap用于将列表的所有项合并为一个列表(FlatMap用于合并两个不同的集合,returns作为一个集合)。