一個函數接受一些輸入,對它作一些事情並建立一個輸出。功能有簽名和正文。若是爲函數提供相同的輸入,則始終得到相同的輸出。簡而言之,這是函數的定義。git
如今咱們將經過仔細研究它們來討論更多功能。咱們將在Swift中探索更高階的函數。將另外一個函數做爲輸入或返回函數的函數稱爲高階函數。編程
在Swift中,咱們使用Map,Filter,Reduce。當咱們使用這些功能時,它彷佛很神奇。此時,您可能不知道幕後發生了什麼。經過函數式編程的思想和方法來映射,過濾和減小工做。即便Swift不是一種純粹的功能語言,它也可讓你作功能性的東西。swift
如今讓咱們一個接一個地看一下背景中發生的事情。首先,咱們將爲某些特定數據類型實現這些函數的基本版本,而後咱們將嘗試實現通用版本。 ####Map 函數 假設咱們有一個整數數組,咱們須要編寫一個函數,在向原始數組的每一個元素添加一些delta值以後返回一個新數組。咱們可使用以下的簡單for循環輕鬆地爲此編寫函數:數組
func increment(by delta: Int, to array: [Int]) -> [Int] {
var result: [Int] = []
for element in array {
result.append(element + delta)
}
return result
}
increment(by: 2, to: arr) //[4, 5, 6, 7]
複製代碼
如今咱們須要另外一個函數,它經過將原始數組的每一個元素加倍來返回一個新數組。爲此,咱們能夠像下面這樣實現它:bash
var arr = [2, 3, 4, 5]
func square(_ array: [Int]) -> [Int]{
var result: [Int] = []
for element in array {
result.append(element * element)
}
return result
}
square(arr) //[4, 9, 16, 25]
複製代碼
若是咱們看一下上面這兩個函數,咱們就能夠發現它們基本上都在作一樣的事情。只有for循環內部的功能不一樣。它們都將Integer數組做爲輸入,使用for循環轉換每一個元素,並返回一個新數組。因此基本上主要是將每一個元素轉換爲新的元素。app
因爲Swift支持高階函數,咱們能夠編寫一個函數,它將獲取一個整數數組,將函數轉換爲輸入,並經過將transform函數應用於原始數組的每一個元素來返回一個新數組。函數式編程
var arr = [2, 3, 4, 5]
func apply(for array: [Int], transform: (Int) -> Int) -> [Int] {
var result: [Int] = []
for element in array {
result.append(transform(element))
}
return result
}
apply(for: arr) { $0 * 3 } //[6, 9, 12, 15]
複製代碼
但仍然存在以上問題:它只返回一個整數數組。例如,若是咱們要求將輸入整數數組轉換爲字符串數組,那麼咱們就不能用這個函數作到這一點。爲此,咱們須要編寫適用於任何類型的通用函數。函數
func genericApply<T>(to array: [Int], transform: (Int) -> T) -> [T] {
var result: [T] = []
for element in array {
result.append(transform(element))
}
return result
}
genericApply(to: arr) { String($0) } //["2", "3", "4", "5"]
複製代碼
咱們能夠在Array擴展中實現泛型函數,以下所示:ui
var array = ["boudhayan", "biswas"]
extension Array {
func map<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
for element in self {
result.append(transform(element))
}
return result
}
}
array.map { $0.count } //[9, 6]
複製代碼
這就是Map函數在Swift中的工做方式。若是咱們須要實現map函數,那麼咱們將像上面同樣實現它。因此基本上,它不會在數組中產生任何魔法 - 咱們能夠很容易地本身定義函數。 ##Filter函數 假設咱們有一個整數數組,咱們只想在數組中保留偶數。咱們能夠經過使用簡單的lo來實現這一點。spa
let integers = [1, 2, 3, 4, 5, 6]
func evenIntegers(from array: [Int]) -> [Int] {
var result: [Int] = []
for element in array where element % 2 == 0 {
result.append(element)
}
return result
}
evenIntegers(from: integers) //[2, 4 6]
複製代碼
再一次,咱們有一個表示項目類文件名的字符串數組,咱們只想保留.swift文件。這也能夠經過如下單循環完成:
let projectFiles = ["classA.swift", "classB.swift", ".gitignore", "ReadMe.md"]
func swiftFiles(from array: [String]) -> [String] {
var result: [String] = []
for element in array where element.hasSuffix(".swift") {
result.append(element)
}
return result
}
swiftFiles(from: projectFiles) //["classA.swift", "classB.swift"]
複製代碼
若是咱們仔細研究上述兩個函數的實現,那麼咱們就能夠理解它們基本上作一樣的事情 - 只有兩個數組的數據類型不一樣。咱們能夠經過實現泛型過濾器函數來歸納這一點,該函數將數組和函數做爲輸入,而且根據includeElement函數的輸出,它決定是否在結果數組中添加元素。
extension Array {
func filter(_ includeElement: (Element) -> Bool) -> [Element] {
var result: [Element] = []
for element in self where includeElement(element) {
result.append(element)
}
return result
}
}
複製代碼
##Reduce函數 假設咱們有一個整數數組,咱們想要實現兩個返回sum和元素乘積的函數。咱們能夠經過使用一個簡單的for循環來實現它:
func sum(_ integers: [Int]) -> Int {
var result = 0
for element in integers {
result += element
}
return result
}
func product(_ integers: [Int]) -> Int {
var result = 1
for element in integers {
result *= element
}
return result
}
sum([1, 2, 3]) //6
product([2, 3, 4]) //24
複製代碼
如今不是擁有一個整數數組,而是說咱們有一個字符串數組,咱們想要鏈接數組中的全部元素:
var names = ["Boudhayan", "Biswas"]
func concatenate(_ strings: [String]) -> String {
var result = ""
for element in strings {
result += element
}
return result
}
concatenate(names) //BoudhayanBiswas
複製代碼
這三個功能基本上都是同樣的。它們將數組做爲輸入,初始化結果變量,迭代數組,並更新結果變量。
從這裏咱們能夠實現一個適用於全部人的通用函數。爲此,咱們須要結果變量的初始值和在每次迭代中更新該變量的函數。
因此咱們能夠用如下定義實現泛型函數:
上述實現對於[Element]類型的任何輸入數組都是通用的。它將計算類型T的結果。要工做,它須要類型T的初始值以分配給結果變量。而後,它須要一個類型(T,元素) - > T的函數,它將在每次迭代中用於for循環內部以更新結果變量。 #感謝閱讀!