这一次,我们将讨论flatMap方法。
flatMap
但是首先让我们考虑一下上下文。
假设我们有一个数组数组:
var arrayOfArrays = [ [1, 1], [2, 2], [3, 3] ]
将其内容乘以2是一个挑战,其结果应如下所示:
// [[2,2],[4,4],[6,6]]
解决此难题的一种方法可能是两次使用map Array的方法,如下所示:
map
//首先迭代数组的数组 arrayOfArrays。 映射 {数组在 //和第二次迭代 //当前数组 返回数组。 映射 {中的整数 //将其内容乘以2 返回整数* 2 }
} // [[2,2],[4,4],[6,6]]
好的,接下来是一个新的挑战,将乘法数组转换为仅一个数组,如下所示:
// [2,2,4,4,6,6]
幸运的是Array的结构为此目的有一个称为joined ,让我们使用它:
Array
joined
var multipliedByTwo = arrayOfArrays。 映射 {数组在 返回数组。 映射 {中的整数 返回整数* 2 } }
var flattened = Array(multipliedByTwo。join()) print(flattened)//输出:[2,2,4,4,6,6]
但是实际上Array的结构已经有一个方法可以同时完成这两项操作,即映射和展平,是的,这是flatMap :
var arrayOfArrays = [[1,1],[2,2],[3,3]]
var flattenedArray = arrayOfArrays。 flatMap {数组在 返回数组。 映射 {中的整数 返回整数* 2 } }
print(flattenedArray)//输出: [2,2,4,4,6,6]
让我们来看另一个例子。
实际上,如果我们迭代数组,则flatMap和map行为类似:
让数字: [整数] = [1、2、3]
让numbersMap =数字。 地图 {return $ 0} print(numbersMap)// [1、2、3]
让numbersFlatMap =数字。 flatMap {返回$ 0} print(numbersFlatMap)// [1、2、3]
但是,如果我们有一系列可选选项,那就会有很大的不同:
让数字: [Int?] = [1, nil ,3]
让numbersMap =数字。 地图 {return $ 0} print(numbersMap)// [可选(1),无,可选(3)]
让numbersFlatMap =数字。 flatMap {返回$ 0} print(numbersFlatMap)// [1,3]
虽然map方法实际上不会更改numbersMap数组结果的任何内容,但是flatMap有两件事:首先从Int?转换项目的类型Int? 转换为Int ,然后删除转换后的转换numbersFlatMap,上的nil项numbersFlatMap,非常简洁。
numbersMap
Int?
Int
numbersFlatMap,
nil
现在让我们结束在实际世界中flatMap的实际使用:
假设我们有一个名为getJSON的方法,该方法基于url将为我们提供来自服务器的字典数组:
getJSON
让url =“ https://jsonplaceholder.typicode.com/users”
getJSON(from:url){(dictionaries: [Dictionary ]? )在 打印(词典) //输出: // 可选([ // [[“ name”:Leanne Graham,“ id”:1], // [..], //]) }
因此,我们创建了一个User结构来存储此数据:
User
struct 用户 {
let id:整数 命名:字符串 let用户名:字符串
在里面? (字典:Dictionary ){ 守护 让id = dictionary [“ id”]为? 诠释 让name = dictionary [“名称”]为? 串, 让username = dictionary [“ username”]为? 串 其他 { 返回零 }
self.id = id self.name =名称 self.username =用户名 }
}
在User类型array中转换数据的经典方法可能是这样的:
array
getJSON(from:url){(dictionaries: [Dictionary ]? )在 如果让字典=字典{ var users = [User]()
用于字典中的字典{ 让用户=用户(字典:词典) 如果让用户=用户{ users.append(用户) } }
打印(用户) // [ User(id:1,name:“ Leanne Graham”,username:“ Bret”),..]
} }
请记住,在创建通过dictionary的新User ,由于我们将init声明为可失败的初始化,因此它有可能无法初始化并返回nil 。
dictionary
init
struct用户{ //一些代码
//失败的初始化 在里面? (字典:Dictionary ){ //一些代码 } }
这就是为什么我们在添加到users数组之前验证用户不是nil的原因。
users
但是还有另一种使用flatMap迭代字典的方法:
//接受字典并返回用户? 让闭包:(Dictionary )->用户?
//初始化闭包 闭包= { 返回用户(字典:字典) }
用户 =字典。 flatMap (关闭)
因此, flatMap将做三件事:
dictionaries
User?
init?)
flatMap完成后,我们将获得[User]数组。
[User]
最后,我们可以进一步减少代码,如下所示:
用户 =字典。 flatMap ( User.init )
如果看到在我们使用闭包的代码,则其类型为:
让闭包: (Dictionary )->用户?
//代码
用户= dictionaries.flatMap( 闭包 )
需要使用Dictionary 作为参数并返回User?
而且,如果您看到User结构的初始化函数:
在里面? (字典:Dictionary ){ //一些代码 }
期望使用Dictionary 作为参数 当然是它的init? 函数调用将返回一个 User?
init?
这就是为什么我们将User.init (这是User结构的init函数)传递给flatMap :
User.init
我们看到了许多使用flatMap方法的示例,但要记住的一些重要要点是:
就是这样,希望对您有所帮助。
感谢您阅读我!