一. 常見的高級函數(shù)簡述
函數(shù) | 函數(shù)用途 | 說明 |
---|---|---|
sorted | 排序 | 常用于數(shù)組和字典(key/value)的排序 |
map | 遍歷 | 每一個元素做一次映射操作 |
flatMap | 遍歷 | 多于用于數(shù)組的降維度 |
compactMap | 遍歷 | 多用于處理數(shù)組的可選值 |
filer | 過濾 | 對數(shù)組元素根據(jù)規(guī)則過濾一次 |
reduce | 多用途 | 基礎(chǔ)思想是將一個序列轉(zhuǎn)換為一個不同類型的數(shù)據(jù)床牧,期間通過一個累加器(Accumulator)來持續(xù)記錄遞增狀態(tài) |
二. 關(guān)于閉包的簡化
1. 閉包的完整格式
{ (parameters) -> return type in // 閉包的參數(shù)和返回類型
statements // 閉包體
}
2. 閉包簡寫的依據(jù)
- 尾隨閉包的用法
- 如果最后一個參數(shù)是閉包茶鹃,可以把閉包放
()
外面 - 如果該閉包參數(shù)是唯一的參數(shù)懂缕,那么
()
可以省略
- 閉包的隱式返回
閉包體只有一條執(zhí)行語句,可以省略return
- 閉包可根據(jù)上下文推斷參數(shù)和返回值類型
在閉包中壁涎,因為包含了上下文的變量和常量的引用,并做了類型推斷 - 簡化閉包的參數(shù)
Swift自動為內(nèi)聯(lián)閉包提供簡寫參數(shù)名稱钢悲,用$0(從0開始焕阿,表示第i個參數(shù)...)
例子說明
let arr = [2, 1, 3]
/// 完整的sorted的寫法
let result = arr.sorted (by: { (a: Int, b: Int) -> Bool in
return a < b
})
// 如果傳入的參數(shù),最后一個參數(shù)是閉包坷随,那么可以把閉包放在()外面
let _ = arr.sorted() { (a: Int, b: Int) -> Bool in
return a < b
}
// 如果傳入的參數(shù)只有一個房铭,且是一個閉包,那么這個()可以省略
let _ = arr.sorted { (a: Int, b: Int) -> Bool in
return a < b
}
// 從單行表達(dá)式閉包中隱式返回(閉包體只有一行代碼温眉,可以省略return)
let _ = arr.sorted { (a: Int, b: Int) -> Bool in
a < b
}
// 閉包可更具上下文推斷參數(shù)和返回值的類型
let _ = arr.sorted { (a, b) -> Bool in
a < b
}
// 簡化閉包的參數(shù)名.使用簡化參數(shù)名缸匪,in和之前的描述可以省略
let _ = arr.sorted {
$0 < $1
}
三. sorted函數(shù)
常用于數(shù)組或者字典的排序操作。
- 數(shù)組的操作
let arr = [2, 1, 3]
/// 數(shù)組降序排序
let result = arr.sorted { (a, b) -> Bool in
return a < b
}
/// 數(shù)組升序排序
let result1 = arr.sorted { (a, b) -> Bool in
return a > b
}
- 字典的操作
let dict = [
"2": "b",
"1": "a",
"3": "c",
]
/// 字典key排序
let result2 = dict.sorted { (a, b) -> Bool in
return a.key < b.key
}
/// 字典value排序
let result3 = dict.sorted { (a, b) -> Bool in
return a.value < b.value
}
- sorted函數(shù)的簡化
// 默認(rèn)從小到大排序
let _ = arr.sorted()
// 從小到大排序
let _ = arr.sorted(by: <)
// 從大到小排序
let _ = arr.sorted(by: >)
四. map函數(shù)
map: 映射
1. 說明
- 可以對數(shù)組中的每一個元素做一次映射操作类溢。
- map函數(shù)返回一個新的數(shù)組凌蔬,并且數(shù)組的類型不要求和原數(shù)組類型一致。
2. 示例
- 對數(shù)組的每一個元素都乘以2一次.
let arr = [1,2,3]
let doubleD = arr.map {
$0 * 2
}
doubleD的結(jié)果為 : [2, 4, 6]
- 獲取的數(shù)組類型跟入?yún)?shù)組類型無關(guān)
let mapArr = ["Swift","Objc","Flutter"]
let mapEndArr = mapArr.map {
$0.count
}
mapEndArr的結(jié)果為: [5, 4, 7]
- 返回值中允許nil的存在
let opArr = ["1","2",nil,"3"]
let opMapArr = opArr.map {
$0
}
opMapArr結(jié)果為: [Optional("1"), Optional("2"), nil, Optional("3")]
五. flatMap 函數(shù)
flat: 使變平
1. flatMap還能把數(shù)組中存有數(shù)組的數(shù)組(二維數(shù)組闯冷、N維數(shù)組)一同打開變成一個新的數(shù)組
let arr3 = [[1, 2, 3], [4, 5, 6]]
let result = arr3.flatMap {
$0
}
let result2 = arr3.flatMap {
$0.map {
$0 + 2
}
}
result的值: [1, 2, 3, 4, 5, 6]
result2的值: [3, 4, 5, 6, 7, 8]
2. flatMap也能把兩個不同的數(shù)組合并成一個數(shù)組砂心,這個合并的數(shù)組元素個數(shù)是前面兩個數(shù)組元素個數(shù)的乘積
let fruits = ["Apple", "Orange", "Puple"]
let counts = [2, 3, 5]
let array = counts.flatMap { count in
fruits.map ({ fruit in
return fruit + " \(count)"
})
}
array的結(jié)果 ["Apple 2", "Orange 2", "Puple 2", "Apple 3", "Orange 3", "Puple 3", "Apple 5", "Orange 5", "Puple 5"]
六. compactMap函數(shù)
compact: 把……壓實(shí);使簡潔蛇耀;使緊密辩诞,壓縮
compactMap,可以把一個集合中的空值去除纺涤,并且返回一個去除nil值得數(shù)組
- 過濾
// 過濾nil译暂,并解包返回值
let arr = [1, 5, nil, 4]
let result = arr.compactMap {
$0
}
// arr的結(jié)果:[1, 5, 4]
- 類型轉(zhuǎn)換
// 類型轉(zhuǎn)換 [Int] -> [String]
let arr1 = [1, 5, 4]
let result1 = arr1.compactMap {
String($0)
}
// arr1的結(jié)果:["1", "5", "4"]
- 篩選數(shù)據(jù)
let arr3 = [1, 2, 3, 4, 5, 6, 7, 8]
let result3 = arr3.compactMap {
$0 % 4 == 0 ? $0 : nil
}
//arr3結(jié)果: [4, 8]
結(jié)果可以看出,雖然閉包的返回值是可選的撩炊,但是這個函數(shù)的返回值結(jié)果并不是可選的外永。
七. filer函數(shù)
file: 提出;銼拧咳;琢磨伯顶;把…歸檔。 filer: 銼磨工人
filer過濾函數(shù),可以過濾掉數(shù)組中不滿足篩選條件的元素砾淌,返回滿足篩選條件的元素所組成的數(shù)組啦撮。
- 篩選出元素 大于 3的元素,并返回集合
let arr = [1, 2, 3, 4, 5]
let result = arr.filter {
$0 > 3
}
// result的結(jié)果: [4, 5]
- 篩選出字符串的長度小于10的字符串
let arr2 = ["Objective-C", "Swift", "HTML", "CSS", "JavaScript"]
let result2 = arr2.filter {
$0.count < 10
}
// result的結(jié)果 ["Swift", "HTML", "CSS"]
- 換種寫法
// 定義篩選規(guī)則函數(shù)
func stringCountLessTen(str: String) -> Bool {
return str.count < 10
}
let result2 = arr2.filter(stringCountLessTen(str:))
八. reduce 函數(shù)
func reduce<Result>(_ initialResult: Result, _ nextPartialResult: (Result, Element) throws -> Result) rethrows -> Result
initialResult
為初始值汪厨,Element
是要處理的元素赃春,處理后返回Result
作為下次閉包的參數(shù)。
- reduce 的基礎(chǔ)思想是將一個序列轉(zhuǎn)換為一個不同類型的數(shù)據(jù),期間通過一個累加器(Accumulator)來持續(xù)記錄遞增狀態(tài)骡和。為了實(shí)現(xiàn)這個方法笆呆,我們會向 reduce 方法中傳入一個用于處理序列中每個元素的結(jié)合(Combinator)閉包 / 函數(shù) / 方法。
- reduce 是 map狭吼、flatMap 或 filter 的一種擴(kuò)展的形式(后三個函數(shù)能干嘛,reduce 就能用另外一種方式實(shí)現(xiàn))
- 獲取數(shù)組中最小的值
let arr = [1, 4, 3, 2]
// 獲取數(shù)組中的最小值
let result = arr.reduce(Int.max, min)
func combinator(accumulator: Int, current: Int) -> Int {
return accumulator + current
}
[1, 2, 3].reduce(0, combine: combinator)
// 執(zhí)行步驟如下
combinator(0, 1) { return 0 + 1 } = 1
combinator(1, 2) { return 1 + 2 } = 3
combinator(3, 3) { return 3 + 3 } = 6
結(jié)果為 6
[1,2,3] 中的每個元素都將調(diào)用一次結(jié)合(Combinator)函數(shù)進(jìn)行處理殖妇。同時我們使用累加器(Accumulator)變量實(shí)時記錄遞增狀態(tài)(遞增并非是指加法)刁笙,這里是一個整型值。
- 計算數(shù)組元素的加減乘除
let arr = [1, 4, 3, 2]
let result2 = arr.reduce(0, +)
let result3 = arr.reduce(0, -)
let result4 = arr.reduce(1, *)
let result5 = arr.reduce(1, /)
// 分別為 10 -10 24 0
- 倒敘數(shù)組
let arr = [1, 4, 3, 2]
let result6 = arr.reduce([Int]()) {
[$1] + $0
}
// [2, 3, 4, 1]
- 多維度的數(shù)據(jù)處理
// 計算出位于臺灣省的人數(shù)谦趣,以及平均年齡
let users: [[String: Any]] = [
["name": "小明", "pro": "山東", "age": 10],
["name": "小花", "pro": "上海", "age": 30],
["name": "小任", "pro": "臺灣", "age": 5],
["name": "小愛", "pro": "臺灣", "age": 5],
["name": "小李", "age": 10] // 沒有錄入省份
]
// 定義一個別名為ProvinceTuples元組疲吸,記錄位于臺灣省的人數(shù)(count)和 總年齡(age)
typealias ProvinceTuples = (count: Int, age: Int)
let result = users.reduce((0, 0)) { (province: ProvinceTuples, user) -> ProvinceTuples in
// 滿足條件 (能獲取到年齡, 能獲取到省并且省是臺灣)
// Swift3時if let和guard場景的where已經(jīng)被Swift4的逗號取代
if let pro = user["pro"] as? String, pro == "臺灣",
let age = user["age"] as? Int
{
return (count: province.count + 1, age: province.age + age)
} else { // 不滿足條件
// 此時的province為(0前鹅, 0)
return province
}
}
let count = result.0
let age = Float(result.1) / Float(count)
// count 為2摘悴, age為5.0