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