高阶函数篇一

54 阅读1分钟

定义Model:

struct UserModel : HandyJSON {
    var name : String?
    var age : Int?
}

定义TabelView的数据源:

var listData[UserModel] = [] 

let userModel_W = UserModel(name : "WY", age : 18)
let userModel_X = UserModel(name : "XY", age : 28)
let userModel_F = UserModel(name : "FY", age : 24)
        
listData.append(userModel_W)
listData.append(userModel_X)
listData.append(userModel_F)

map( _ :)

对集合中的每个元素进行转换,返回一个新的数组

如果想要在拿到只有name的数据源该怎么处理呢:

一般就是通过for循环把想要的数据添加进一个新的数组内

var nameData : [String] = []

for model in listData {
    if let name = model.name {
       nameData.append(name)
    }
}
let nameArray : NSMutableArray = []

for model in listData {
    if let name = model.name {
       nameArray.add(name)
    }
}

如果使用map()的高阶函数一切就变的简单了

let nameListData = listData.map( { $0.name } )
print("name===\(nameListData)")

//输出
name = [optional("WY"),optional("XY"),optional("FY")]

底层逻辑:

map()是通过以下的协议扩展实现的:

func map<T>(_ transform : (Element) throws -> T) rethrows -> [T]

// 该协议方法使用了T泛型来作为参数传入,返回一个使用泛型来作为值的数组

// 通过**(Element) throws -> T**闭包的形式用来抛出错误

// 闭包的返回值和函数的返回类型都是泛型(没有固定类型),在需要使用的时候来决定类型

map()的主要用于转换(transform)

大致的实现原理:

  • 创建一个新的空数组,容量预分配为原集合的容量
  • 遍历原集合的每个元素
  • 对每个元素应用转换闭包
  • 将转换结果追加到新数组中
  • 返回新数组

其他功能:

因其传入的是泛型因此不仅仅能处理数组,也可以处理字典

// 对字典键值转换
let dict = ["a": 1, "b": 2, "c": 3]
let newDict = dict.map { ($0.key.uppercased(), $0.value * 2) }
// [("A", 2), ("B", 4), ("C", 6)]

// 取key值
let dict = ["a" : 1, "b" : 2, "c" : 3]
let keyData = dict.map {($0.key)}

//输出
keyData === ["b","a","c"]
// 输出的Key数组的顺序并不是固定的
// 类型转换
let strings = ["1", "2", "3"]
let numbers = strings.map { Int($0) }  // [Int?]
// 条件转换
let numbers = [1, 2, 3, 4, 5]
let evenSquares = numbers.map { $0 % 2 == 0 ? $0 * $0 : $0 }
// [1, 4, 3, 16, 5]

compactMap(_:)

和map( _ :)的最大区别就是 map( _ :) 在对集合元素进行转换过程中并不会过滤掉nil

let userModel_T = UserModel(name : nil, age : 24)
listData.append(userModel_T)

//分别进行map( _ :)和compactMap(_:)
let nameListData = listData.map( { $0.name } )
print("nameListData===\(nameListData)")
nameListData = [optional("WY"), optional("XY"), optional("FY"), nil]


let newData = listData.compactMap( { $0.name } )
print("newData===\(newData)")
newData = ["WY", "XY", "FY"]

从输出结果上可以看出有两大不同

  • map( _ :)并不会过滤掉nil项,compactMap(_:) 则自动过滤了nil值
  • map( _ :)的转过结果是可选值内容,而compactMap(_:)返回的是一个非可选值的新数组