Swift map链式调用问题:添加print失效及flatMap与map差异咨询
Swift中flatMap的常见疑问解答
问题背景
有两段Swift代码,第一段可正常运行,实现嵌套数组的编号格式化输出:
var raceResults = [["one","two","four"],["two","one","five","six"],["two","one","four","ten"],["one","two","four"]] let numberedRaceResults = raceResults .enumerated() .flatMap { outterOffset, raceResult in raceResult .enumerated() .map { innerOffset, element in "\(outterOffset).\(innerOffset). \(element)" } } for numberedResult in numberedRaceResults { print(numberedResult) }
但在flatMap的闭包中添加两个print语句后,控制台输出看起来“异常”;若将flatMap替换为map,也无法得到预期的一维编号数组。目前仅了解flatMap可过滤nil值,希望解答以下问题:
- 为何添加print语句会导致输出异常?
- flatMap相比map除过滤nil外还有哪些功能,导致替换后无法得到预期结果?
添加print语句后的代码如下:
var raceResults = [["one","two","four"],["two","one","five","six"],["two","one","four","ten"],["one","two","four"]] let numberedRaceResults = raceResults .enumerated() .flatMap { outterOffset, raceResult in print(outterOffset) print(raceResult) raceResult .enumerated() .map { innerOffset, element in "\(outterOffset).\(innerOffset). \(element)" } } for numberedResult in numberedRaceResults { print(numberedResult) }
问题解答
1. 添加print语句的影响
添加print语句并没有导致代码逻辑异常,只是会在控制台额外输出外层索引(outterOffset)和对应子数组(raceResult)的内容,这些额外输出会和最终的编号结果穿插显示,让你误以为代码失效。
Swift闭包默认会返回最后一行语句的结果,你添加的print是前序执行的语句,不会改变闭包的返回值——numberedRaceResults的实际内容和第一段代码完全一致,只是控制台多了额外的调试输出。
2. flatMap与map的核心差异
flatMap除了能过滤Optional类型中的nil(Swift 4.1后该功能已由compactMap专门承担),还有一个关键功能:将嵌套序列扁平化。
- 使用
map时,raceResults.enumerated().map { ... }会返回[[String]]类型的二维数组:因为每个闭包返回的是一个[String](内层map的结果),所以最终结果是“数组的数组”。遍历这个二维数组时,你得到的是一个个子数组,而非单个的编号字符串,自然无法得到预期的单行输出。 - 使用
flatMap时,它会将每个闭包返回的序列(这里是[String])中的元素逐一取出,合并成一个一维数组[String]。这正是你需要的结果:所有编号后的字符串都在同一个数组里,遍历就能逐个输出。
举个简化例子:
- 输入
[[1,2],[3,4]],用map处理每个子数组返回自身,结果还是[[1,2],[3,4]]; - 用
flatMap处理的话,结果会变成[1,2,3,4]。
内容的提问来源于stack exchange,提问作者user1845926
相关产品推荐
相关产品推荐

