一尘不染

Swift中flatMap和compactMap之间的区别

swift

Swift 4.1中 似乎flatMap已弃用。但是在 Swift 4.1中
有一个新方法compactMap正在做同样的事情?有了它,flatMap您可以变换集合中的每个对象,然后删除所有为零的项目。
像flatMap一样

let array = ["1", "2", nil] 
array.flatMap { $0 } // will return "1", "2"

像compactMap

let array = ["1", "2", nil] 
array.compactMap { $0 } // will return "1", "2"

compactMap 在做同样的事情。

这两种方法有什么区别?苹果为何决定重命名该方法?


阅读 438

收藏
2020-07-07

共1个答案

一尘不染

Swift标准库为flatMap函数定义了3个重载:

Sequence.flatMap<S>(_: (Element) -> S) -> [S.Element]  
Optional.flatMap<U>(_: (Wrapped) -> U?) -> U?  
Sequence.flatMap<U>(_: (Element) -> U?) -> [U]

可以通过两种方式滥用最后一个重载函数:
考虑以下struct和array:

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之前的快速版本,则将获得以下内容的转换列表:

["Osame", "Masoud", "Mehdi"]

但在较新的版本中String符合Collection协议,因此,您对的使用flatMap()将匹配第一个重载函数,而不是第三个重载函数,并且将为您带来转换后的值的平坦结果:

["O", "s", "a", "m", "e", "M", "a", "s", "o", "u", "d", "M", "e", "h", "d", "i"]

结论:他们弃用了flatMap()的第三重载。
由于这些误用,迅速团队决定将第三重载弃用到flatMap函数。Optional到目前为止,他们针对需要处理s
的情况的解决方案是引入一个名为的新函数compactMap(),它将为您带来预期的结果。

2020-07-07