书接上回 [flatMap]对Optional类型进行flatMap的实验(上)
//请用flatMap扁平化以下所有数组,不允许强制解包(如值为nil会崩掉的...)
let array1:[[Int]] = [[1, 2, 3], [4, 5, 6]]
let array2:[[Int]]? = [[1, 2, 3], [4, 5, 6]]
let array3:[[Int]?] = [[1, 2, 3], [4, 5, 6]]
let array4:[[Int]?]? = [[1, 2, 3], [4, 5, 6]]
let array5:[[Int?]] = [[1, 2, 3], [4, 5, 6]]
let array6:[[Int?]]? = [[1, 2, 3], [4, 5, 6]]
let array7:[[Int?]?] = [[1, 2, 3], [4, 5, 6]]
let array8:[[Int?]?]? = [[1, 2, 3], [4, 5, 6]]
看答案之前我们先注意一点:第2、4、6、8个数组为Optional
我们知道:Optional不解包,直接使用flatMap的话,返回的对象依然是Optional
因此第2、4、6、8个数组最终结果必然是还是Optional
为方便调试,先来顶一个调试方法
func log(_ tag:String, _ any:Any)
{
print("--------\(tag)--------")
print(any)
print(type(of: any))
print("----------------------\n")
}
以下是答案和结果
log("array1", array1.flatMap{ $0 })
log("array2", array2?.flatMap{ $0 })
log("array3", array3.flatMap{ $0 }.flatMap{ $0 })
log("array4", array4?.flatMap{ $0 }.flatMap{ $0 })
log("array5", array5.flatMap{ $0 }.flatMap{ $0 }) //array5有两种写法
log("array5", array5.flatMap{ $0.flatMap{ $0 } })
log("array6", array6?.flatMap{ $0.flatMap{ $0 } })
log("array7", array7.flatMap{ $0 }.flatMap{ $0.flatMap{ $0 } })
log("array8", array8?.flatMap{ $0?.flatMap{ $0 } }.flatMap{ $0 })
//--------array1--------
//[1, 2, 3, 4, 5, 6]
//Array
//----------------------
//--------array2--------
//Optional([1, 2, 3, 4, 5, 6])
//Optional>
//----------------------
//--------array3--------
//[1, 2, 3, 4, 5, 6]
//Array
//----------------------
//--------array4--------
//Optional([1, 2, 3, 4, 5, 6])
//Optional>
//----------------------
//--------array5--------
//[1, 2, 3, 4, 5, 6]
//Array
//----------------------
//--------array5--------
//[1, 2, 3, 4, 5, 6]
//Array
//----------------------
//--------array6--------
//Optional([1, 2, 3, 4, 5, 6])
//Optional>
//----------------------
//--------array7--------
//[1, 2, 3, 4, 5, 6]
//Array
//----------------------
//--------array8--------
//Optional([1, 2, 3, 4, 5, 6])
//Optional>
//----------------------
接下来逐个解释一下原因:
let array1:[[Int]] = [[1, 2, 3], [4, 5, 6]]
log("array1", array1.flatMap{ $0 })
//结果:[1, 2, 3, 4, 5, 6]
//这个只是普通的flatMap降维
let array2:[[Int]]? = [[1, 2, 3], [4, 5, 6]]
log("array2", array2?.flatMap{ $0 })
//结果:Optional([1, 2, 3, 4, 5, 6])
//Optional不解包直接使用flatMap,虽然一样可以降维数组,但返回的对象依然是Optional
let array3:[[Int]?] = [[1, 2, 3], [4, 5, 6]]
log("array3", array3.flatMap{ $0 }.flatMap{ $0 })
//结果:[1, 2, 3, 4, 5, 6]
//array3是一个元素为Optional<[Int]>的数组,第一个flatMap的作用是安全解包元素和去nil,第二个flatMap才是降维数组
let array4:[[Int]?]? = [[1, 2, 3], [4, 5, 6]]
log("array4", array4?.flatMap{ $0 }.flatMap{ $0 })
//结果:Optional([1, 2, 3, 4, 5, 6])
//原理其实就是array2和array3的合并
let array5:[[Int?]] = [[1, 2, 3], [4, 5, 6]]
log("array5", array5.flatMap{ $0 }.flatMap{ $0 }) //方法一
log("array5", array5.flatMap{ $0.flatMap{ $0 } }) //方法二
//结果:[1, 2, 3, 4, 5, 6]
//我们先来看一个中间步骤,方便理解
log("sample", array5.flatMap{ $0 })
//--------sample--------
//[Optional(1), Optional(2), Optional(3), Optional(4), Optional(5), Optional(6)]
//Array>
//----------------------
//方法一中,第一个flatMap起到的是降维的作用,把数组降维成Array>的,第二个flatMap则把降维后为Array>的数组安全解包和去nil
//方法二中,依然是第一个flatMap降维,第二个flatMap安全解包和去nil,但是具体为什么……笔者还没参透,望大神解答
let array6:[[Int?]]? = [[1, 2, 3], [4, 5, 6]]
log("array6", array6?.flatMap{ $0 }.flatMap{ $0 })
//结果:Optional([1, 2, 3, 4, 5, 6])
//array2和array5的合并
let array7:[[Int?]?] = [[1, 2, 3], [4, 5, 6]]
log("array7", array7.flatMap{ $0 }.flatMap{ $0.flatMap{ $0 } })
//结果:[1, 2, 3, 4, 5, 6]
//第一个flatMap安全解包和去nil,把数组转变成 [ [Int?] ]
//第二个和第三个flatMap和array5同理
let array8:[[Int?]?]? = [[1, 2, 3], [4, 5, 6]]
log("array8", array8?.flatMap{ $0?.flatMap{ $0 } }.flatMap{ $0 })
//结果:Optional([1, 2, 3, 4, 5, 6])
//array2和array7的合并
附上关于flatMap的文档截图
flatMap为什么有降维和安全解包两种,实际就是因为flatMap有两个,但是参数和返回值不同
我们在使用flatMap时候(尤其是flatMap{ $0 }这样的省略式),swift会根据上下文自动推断使用哪一个