Swift标准库为flatMap
函数定义了3种重载:
Sequence.flatMap<S>(_: (Element) -> S) -> [S.Element]
Optional.flatMap<U>(_: (Wrapped) -> U?) -> U?
Sequence.flatMap<U>(_: (Element) -> U?) -> [U]
最后一个重载函数可能会被误用两种方式:
考虑以下结构体和数组:
struct Person {
var age: Int
var name: String
}
let people = [
Person(age: 21, name: "Osame"),
Person(age: 17, name: "Masoud"),
Person(age: 20, name: "Mehdi")
]
第一种方法:增加和删除封装:
如果您需要获取包含在people
数组中的人的年龄数组,您可以使用两个函数:
let flatMappedAges = people.flatMap({$0.age}) // prints: [21, 17, 20]
let mappedAges = people.map({$0.age}) // prints: [21, 17, 20]
在这种情况下,map
函数将完成任务,不需要使用flatMap
,因为两者产生相同的结果。此外,在使用flatMap
的这种用例中存在无用的包装和解包过程。(闭包参数用Optional包装其返回值,而flatMap的实现在返回值之前会取消Optional的包装)
第二种方法 - 字符串符合集合协议:
假设你需要从people
数组中获取人名列表。您可以使用以下代码:
let names = people.flatMap({$0.name})
如果您使用的是4.0之前的Swift版本,则会获得一个转换后的列表
["Osame", "Masoud", "Mehdi"]
但在更新的版本中,String
符合Collection
协议,因此,您对flatMap()
的使用将匹配第一个重载函数而不是第三个,并为您转换后的值提供一个扁平化的结果:
["O", "s", "a", "m", "e", "M", "a", "s", "o", "u", "d", "M", "e", "h", "d", "i"]
那么,他们是如何解决这个问题的?他们弃用了flatMap()的第三个重载
由于这些误用,Swift团队决定弃用flatMap函数的第三个重载。到目前为止,他们解决需要处理Optional
的情况的方法是引入一个名为compactMap()
的新函数,该函数将给你所期望的结果。
let mappedAges = people.map({$0.name})
这行代码使用了$0.name
而不是$0.age
。 - Toni Sučić