Swift高阶函数使用方式
1. map
1
2
3
4
{
(Element) -> T in
// Element的处理代码
}
简单说就是数组中每个元素通过某个方法进行操作,最后返回一个新的数组。
白话点就是:遍历数组每个元素并都进行相同的操作,返回操作后获取到的值
1
2
3
4
let test = [1, 2, 3]
// 获取每个值的平方
let squares = test.map { $0 * $0 }
// [1, 4, 9]
2. flatMap
降维和过滤,swift4.1之后只有降纬,过滤nil给了compactMap,因为flatMap违背了单一功能原则
过滤nil,解析首层元素,若有nil
则过滤,就不会降维
1
2
3
4
let optLatticeNumbers = [[1, Optional(2), 3], [3, nil, 5], nil]
// 解析首层元素, 若有nil则过滤, 就不会降维
let flatMapArr2 = optLatticeNumbers.flatMap { $0 }
// [[1, 2, 3], [3, nil, 5]]
降纬,二维数组变成一维数组,解析首层元素,若没有nil
,则会降维
1
2
3
4
let latticeNumbers = [[1, Optional(2), 3], [3, nil, 5]]
// 解析首层元素, 若没有nil, 则会降维
let flatMapArr = latticeNumbers.flatMap { $0 }
// [1, 2, 3, 3, nil, 5]
3. compactMap
compactMap 方法同 map 方法比较类似,只不过它返回后的数组中不存在 nil(自动把 nil 给剔除掉),同时它会把 Optional 解包。
1
2
3
4
5
6
7
8
9
let test = ["rambo", "jhon", "", "test"]
let nonil = test2.compactMap { (str) -> String? in
if str.count > 0 {
return str
} else {
return nil
}
}
// ["rambo", "jhon", "test"]
4. sort
对原集合进行给定条件排序。无返回值,直接修改原集合,所以这个集合应该是可变类型的。
1
2
3
var sortArr = [1, 2, 3, 4, 5]
// 从小到大排序
sortArr.sort { $0 < $1 }
5. sorted
sorted函数
与sort函数
对应。将集合进行给定条件排序,返回一个新的集合,不修改原集合。
1
2
3
let numbers = [1, 2, 3, 4, 5]
// 从小到大排序
var sortArr = numbers.sorted { $0 < $1 }
6. filter
filter 方法用于过滤元素,即筛选出数组元素中满足某种条件的元素。
1
2
3
4
{
(Element) -> Bool in
// Element的条件判断处理代码
}
1
2
3
4
let numbers = [1, 2, 3, 4, 5]
// 小于3的数
let arr = numbers.filter { $0 < 3 }
// [1, 2]
7. reduce
reduce 方法把数组元素组合计算为一个值,并且会接受一个初始值,这个初始值的类型可以和数组元素类型不同。
1
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
initialResult
为初始值,Element
是要处理的元素,处理后返回Result
作为下次闭包的参数。
- reduce 的基础思想是将一个序列转换为一个不同类型的数据,期间通过一个累加器(Accumulator)来持续记录递增状态。为了实现这个方法,我们会向 reduce 方法中传入一个用于处理序列中每个元素的结合(Combinator)闭包 / 函数 / 方法。
- reduce 是 map、flatMap 或 filter 的一种扩展的形式(后三个函数能干嘛,reduce 就能用另外一种方式实现)
具体例子,计算所有学生的年龄加载一起是多少。
1
2
3
4
let totalAges = stus.reduce(0) { (result, stu) in
return result + stu.age
}
print(totalAges) // 62
该函数的第一个参数为初始值,后面元组中的第一个参数为每次计算的结果result,第二个参数为每次遍历的元素stu。最后将计算的结果返回。
1
2
3
let reduceString = ["C", "O", "D", "E"].reduce("word: ") { result, num in
return result + num
}// "word: CODE"
8. prefix
正向取满足条件的元素,进行新集合创建。一旦出现不满足条件的元素,则跳出循环,不再执行。
1
2
3
4
let numbers = [7, 6, 10, 9, 8, 1, 2, 3, 4, 5]
// 找到第一个满足小于10的条件就跳出循环
let prefixArr = numbers.prefix { $0 < 10 }
// [7, 6]
prefix
相关函数:
upTo
: 正向取元素创建数组, 包含小于指定index的元素1 2 3
// 取到下标为4的元素结束 let prefixUpToArr = numbers.prefix(upTo: 5) // [7, 6, 10, 9, 8]
through
: 正向取元素创建数组, 包含小于等于指定index的元素1 2 3
// 取到下标为2的元素结束 let prefixThroughArr = numbers.prefix(through: 2) // [7, 6, 10]
maxLength
: 正向取元素创建数组, 包含指定的元素个数1 2 3
// 取6个 let prefixMaxLengthArr = numbers.prefix(6) // [7, 6, 10, 9, 8, 1]
9. drop函数
与prefix
函数对应。正向跳过满足条件的元素,进行新集合创建。一旦出现不满足条件的元素,则跳出循环,不再执行。
1
2
3
4
let numbers = [7, 6, 10, 9, 8, 1, 2, 3, 4, 5]
// 跳过符合条件<10的数据,取剩下的
let dropArr = numbers.drop { $0 < 10 }
// [10, 9, 8, 1, 2, 3, 4, 5]
drop
相关函数:
dropFirst
: 正向跳过元素创建数组, 跳过指定元素个数, 缺省值为1
1
2
3
// 丢弃前面三个
let dropFirstArr = numbers.dropFirst(3)
// [9, 8, 1, 2, 3, 4, 5]
dropLast
: 返向跳过元素创建数组, 跳过指定元素个数, 缺省值为1
1
2
3
// 丢弃后面5个
let dropLastArr = numbers.dropLast(5)
// [7, 6, 10, 9, 8]
10. first函数
正向找出第一个满足条件的元素。
1
2
3
let numbers = [7, 6, 10, 9, 8, 1, 2, 3, 4, 5]
let first = numbers.first { $0 < 7 }
// 6
11. last函数
与first
函数对应。反向找出第一个满足条件的元素。
1
2
3
let numbers = [7, 6, 10, 9, 8, 1, 2, 3, 4, 5]
let last = numbers.last { $0 > 5 }
// 8
12. firstIndex函数
正向找出第一个满足条件的元素下标。
1
2
3
let numbers = [7, 6, 10, 9, 8, 1, 2, 3, 4, 5]
let firstIndex = numbers.firstIndex { $0 < 7 }
// 1
13. lastIndex函数
反向找出第一个满足条件的元素下标。
1
2
3
let numbers = [7, 6, 10, 9, 8, 1, 2, 3, 4, 5]
let lastIndex = numbers.lastIndex { $0 > 5 }
// 4
14. partition函数
按照条件进行重新排序,不满足条件的元素在集合前半部分,满足条件的元素后半部分,但不是完整的升序或者降序排列。 返回值为排序完成后集合中第一个满足条件的元素下标。
1
2
3
4
var partitionNumbers = [20, 50, 30, 10, 40, 20, 60]
let pIndex = partitionNumbers.partition { $0 > 30 }
// partitionNumbers = [20, 20, 30, 10, 40, 50, 60]
// pIndex = 4
15. min函数
按条件排序后取最小元素。
1
2
3
let numbers = [7, 6, 10, 9, 8, 1, 2, 3, 4, 5]
let min = numbers.min { $0 % 5 < $1 % 5 }
// 10
min()
函数,自然升序取最小。
1
2
let minDefault = numbers.min()
// 1
16. max函数
按条件排序后取最大元素。
1
2
3
let maxDictionary = ["aKey": 33, "bKey": 66, "cKey": 99]
let max = maxDictionary.max { $0.value < $1.value }
// (key "cKey", value 99)
max()
函数,自然升序取最大。
1
2
let maxDefault = numbers.max()
// 10
17. removeAll函数
移除原集合中所有满足条件的元素。无返回值,直接修改原集合,所以这个集合应该是可变类型的。
1
2
3
4
let numbers = [7, 6, 10, 9, 8, 1, 2, 3, 4, 5]
var removeArr = numbers
removeArr.removeAll { $0 > 6 }
// [6, 1, 2, 3, 4, 5]
18. 集合遍历
forEach
函数:
1
2
3
numbers.forEach { num in
print(num)
}
for-in
函数:
1
2
3
for num in numbers where num < 5 {
print(num)
}
与enumerated()
函数配合使用:
1
2
3
for (index, num) in numbers.enumerated() {
print("\(index)-\(num)")
}
关于集合遍历的性能问题,可以看这里enumerated() 和 enumerateObjectsUsingBlock。
19. shuffled函数
shuffled
函数,打乱集合中元素的的顺序。
1
2
3
let ascendingNumbers = 0...9
let shuffledArr = ascendingNumbers.shuffled()
// [3, 9, 2, 6, 4, 5, 0, 1, 7, 8]
20. contains函数
contains
函数,判断集合中是否包含某元素。
1
2
3
4
let containsBool = numbers.contains(8)
let containsBool1 = numbers.contains(11)
// true
// false
21. split和joined函数
split
函数,字符串的函数,按条件分割字符串,为子字符串创建集合。与Objective-C
中的componentsSeparatedByString:
方法类似。
1
2
3
4
5
6
7
let line = "123Hi!123I'm123a123coder.123"
let splitArr = line.split { $0.isNumber }
// ["Hi!", "I'm", "a", "coder."]
// 也可指定字符
let splitArr2 = line.split(separator: "1")
// ["23Hi!", "23I'm", "23a", "23coder.", "23"]
joined
函数,数组元素连接指定字符拼接成一个字符串。与Objective-C
中的componentsJoinedByString:
方法类似。
1
2
3
4
5
6
let joined = splitArr.joined(separator: "_")
// "Hi!_I'm_a_coder."
// 也可以只传入字符
let joined2 = splitArr2.joined(separator: "#")
// "23Hi!#23I'm#23a#23coder.#23"
22. zip函数
将两个数组合并为一个元组组成的数组。
1
2
3
4
5
6
let titles = ["aaa", "bbb", "ccc"]
let numbers = [111, 222, 333]
let zipA = zip(titles, numbers)
for (title, num) in zipA {
print("\(title)-\(num)")
}
打印结果:
1
2
3
aaa-111
bbb-222
ccc-333