Swift中的数组有一些高级API非常好用(用法类似JavaScript
)。
一、Array的常见操作
基础代码:
1 | var arr = [1, 2, 3, 4] |
1.1. map(映射)
遍历每一个元素,元素在函数(闭包表达式)中处理完成后把返回值放到新的数组,返回一个新数组。
示例代码:
1 | var arr2 = arr.map { |
注意:
map
的闭包表达式返回值类型是泛型,也就意味返回新数组元素的类型可以是任意类型。
1.2. filter(过滤)
遍历每一个元素,满足函数(闭包表达式)条件(true)后把元素放到新的数组,返回一个新数组。
示例代码:
1 | var arr2 = arr.filter { |
1.3. reduce(累计)
第一个参数是初始值。第二个参数是闭包表达式(第一个参数是闭包返回值,首次传入的参数值是reduce
函数的第一个参数即初始值,第二个参数是数组元素,函数返回值作为下一次遍历时闭包表达式的第一个参数),数组遍历完成后把结果返回。
示例代码:
1 | var arr2 = arr.reduce(0) { |
使用reduce
实现map
功能。
示例代码:
1 | var arr2 = arr.reduce([]) { $0 + [$1 * 2] } |
使用reduce
实现filter
功能。
示例代码:
1 | var arr2 = arr.reduce([]) { $1 % 2 == 0 ? $0 + [$1] : $0 } |
1.4. flatMap(元素平铺映射)
map
是返回一个泛型元素数组,返回值是什么,最终返回的数组元素就是什么。flatMap
返回元素值是Sequence
类型,而数组就是Sequence
类型,如果flatMap
传入的是一个数组,函数会把传入的数组所有元素平铺放到一个新的数组中返回。
示例代码:
1 | // repeating:重复元素 count:重复次数 |
1.5. compactMap(元素压缩映射)
compactMap
可以自动解包可选值,非nil
元素会被解包放到新的数组中。
示例代码:
1 | var arr = ["123", "idbeny", "hello", "-20"]; |
1.6. lazy
直接使用map
会一次性把数组所有元素都遍历一遍。
示例代码:
1 | let result = arr.map { |
上面示例可以看出,使用数组result
前,数组已经被map
遍历完成。有没有可能用到result
时再去执行map
?可以的,使用lazy
。
示例代码:
1 | let result = arr.lazy.map { |
上面示例很明显看到只有用到result
时才去执行map
函数。
二、Optional的map和flatMap
map
对可选类型操作时,闭包表达式传入的是解包后的值,map
返回的类型也是可选类型。如果传入的可选类型是nil
,返回的也是nil
。
示例代码一:
1 | var num1: Int? = 10 |
如果map
传入的是可选类型,闭包表达式中返回的也是可选类型,最终返回的是双重可选类型(会自动再次包装一层可选类型)。但是flatMap
发现返回的是可选类型时不会再次包装,如果不是可选类型就会再次包装一层。
示例代码二:
1 | var num1: Int? = 10 |
应用场景一:
下面代码中num2
和num3
是等价的。
1 | var num1: Int? = 10 |
应用场景二:
下面代码中date1
和date2
是等价的。
1 | var fmt = DateFormatter() |
上面示例中为什么使用flatMap
,不使用map
?因为fmt.date
函数返回值是可选类型,使用map
会被再次包装一层可选类型。
应用场景三:
下面代码中str1
和str2
是等价的。
1 | var score: Int? = 98 |
??
前面如果是可选类型,后面是非可选类型,当可选类型值非nil
时会自动解包。
应用场景四:
根据name
找到对应Person
实例。getPerson1
和getPerson2
是等价的。
数组的first
函数可以根据索引找到第一个符合要求的对应元素,firstIndex
可以根据索引找到第一个符合要求的对应元素(这两个函数的闭包表达式入参都是数组元素,返回值都是Bool
类型,如果为true
就把对应索引或元素返回并且停止遍历。需要注意的是返回值都是可选类型)。
1 | struct Person { |
应用场景五:
字典转模型。下面示例中p1
和p2
的代码是等价的。
1 | struct Person { |