在swift中托慨,對諸如Array, Dictionary集合類型使用map, filter, reduce進(jìn)行操作是非常方便的事情扫皱,隨著對swift語言的了解加深埠胖,開發(fā)者將越來越習(xí)慣间聊、越來越喜歡這種抽象度較高的語法族购,但愿如此壳贪,[流汗]。如果你沒有函數(shù)式語言編程的相關(guān)經(jīng)驗寝杖,在處理集合類型時违施,你的第一直覺可能是使用for-loop循環(huán)。本篇文章瑟幕,是關(guān)于swift中map, filter, reduce的基本概念和使用的入門介紹磕蒲,也是希望能借此文章幫助讀者改變編程習(xí)慣和編程思維留潦,提升swift開發(fā)效率。
Map-遍歷任意集合類型
我們可以使用for循環(huán)來計算一個數(shù)組中每個元素的平方值辣往,如下代碼所示
let values = [2.0, 4.0, 5.0, 7.0]
var squares: [Double] = []
for value in values {
squares.append(value*value)
}
下面看一看愤兵,使用map來實(shí)現(xiàn)同樣的功能
let values = [2.0,4.0,5.0,7.0]
let squarses = values.map{$0*$0}
print(squarses)
let c = values.map{m in m * 3}
print(c)
//[4.0, 16.0, 25.0, 49.0]
//[6.0, 12.0, 15.0, 21.0]
基本格式
let 常量名 = 要遍歷的數(shù)組.map{$0*$0}
print("打印出數(shù)組,驗證函數(shù)")
// $0表示當(dāng)前遍歷的集合對象中的一個元素排吴,就這樣,不要想得太復(fù)雜懦鼠;也請多想一點(diǎn)點(diǎn)钻哩,查找相關(guān)資料多做了解。
Filter - 過濾 篩選
Filter肛冶,顧名思義街氢,就是過濾、篩選的意思睦袖,對于一個集合對象而言珊肃,filter函數(shù)的作用是遍歷該集合,然后將該集合中符合某些特定條件的元素組成新的數(shù)組馅笙,并返回該新數(shù)組伦乔,也就是說選擇集合中符合條件的元素醇坝,過濾掉不符合條件的元素
let digits = [1, 4, 10, 15]
let even = digits.filter { $0 % 2 == 0 }
// [4, 10]
Reduce - 組合
Reduce凭疮,我所了解的英文翻譯是減少、降低铡俐,在此處這樣理解是不正確的皿淋,在swift函數(shù)式編程的概念中招刹,reduce有“組合、歸納”的意思窝趣,使用reduce函數(shù)可以將一個集合中的所有元素組合起來疯暑,生成一個新的值并返回該值
Reduce函數(shù)接收兩個參數(shù),一個初始值和一個組合閉包(combine closure)哑舒,例如妇拯,將一個數(shù)組中的各個元素與一個初始值10相加,可以使用reduce函數(shù)散址,如下代碼所示
let items = [2.0, 4.0, 5.0, 7.0]
let total = items.reduce(10, combine: +)
// 28.0
同樣乖阵,這也適用于使用+將數(shù)組中的string進(jìn)行拼接,如下代碼
let codes = ["abc", "def", "ghi"]
let text = codes.reduce("", combine: +)
// "abcdefghi"
FlatMap-連接
Flat是什么意思呢预麸?它表示平坦的瞪浸、扁平的,這是它的形容詞意思吏祸,它的動詞意思有“使...扁平”对蒲,在swift中flatMap表示將多個集合對象扁平化為一個數(shù)組钩蚊,也就說把多個集合連接成一個集合,下面的代碼展示了最簡單的flatMap使用
let collections = [[5, 2, 7], [4, 8], [9, 1, 3]]
let flat = collections.flatMap { $0 }
// [5, 2, 7, 4, 8, 9, 1, 3]
甚至蹈矮,flatMap還“知道”可選值的概念砰逻,它將會把集合中的nil元素移除掉,如下代碼所示:
let people: [String?] = ["Tom", nil, "Peter", nil, "Harry"]
let valid = people.flatMap { $0 }
// ["Tom", "Peter", "Harry"]
再看看filter和flatMap組合使用的例子泛鸟,先將一個數(shù)組中的多個字?jǐn)?shù)組扁平化(flat)為一個數(shù)組蝠咆,然后再使用過濾(filter)篩選出數(shù)組中的偶數(shù),如下代碼所示
let collections = [[5, 2, 7], [4, 8], [9, 1, 3]]
// 此處even表示偶數(shù)
let onlyEven = collections.flatMap {
intArray in intArray.filter { $0 % 2 == 0 }
// result -- [2, 4, 8]
}
簡寫如下
let collections = [[5, 2, 7], [4, 8], [9, 1, 3]]
let onlyEven = collections.flatMap { $0.filter { $0 % 2 == 0 }}
// result -- [2, 4, 8]
最后一個例子北滥,使用flatMap和reduce來計算一個數(shù)組中所有整型子數(shù)組的內(nèi)的所有元素相加計算的和(sum)刚操,還是使用閉包的簡寫語法和完整的規(guī)范寫法,如下代碼所示:
let collections = [[5, 2, 7], [4, 8], [9, 1, 3]]
let sums = collections.flatMap { $0.reduce(0, combine:+) }
let sums2 = collections.flatMap {
intArray in intArray.reduce(0, combine:+)
}
Chaining 鏈?zhǔn)秸Z法
我們可以通過鏈?zhǔn)秸Z法來使用swift的map, filter, reduce以及flatMap再芋,例如計算集合中大于等于7的數(shù)字的和菊霜,可以先使用filter篩選,然后在使用reduce求和济赎,如下代碼所示:
let marks = [4, 5, 8, 2, 9, 7]
let totalPass = marks.filter { $0 >= 7}.reduce(0, combine: +)
// result - 24
再比如鉴逞,求一個數(shù)組中的元素的平方值是偶數(shù)的集合,可以先通過map計算所有平方值司训,然后在通過filter篩選出偶數(shù)构捡,如下代碼所示:
let numbers = [20, 17, 35, 4, 12]
let evenSquares = numbers.map { $0 * $0 }.filter { $0 % 2 == 0 }
// result -- 400, 16, 144
其實(shí)稍微思考也覺得這沒什么高深,因為map和filter返回的是一個數(shù)組壳猜,我們當(dāng)然可以對返回的數(shù)組繼續(xù)使用map, filter, reduce以及flatMap操作叭喜。
一些小小的總結(jié)
以后在使用swift編碼的過程中,當(dāng)你意識到自己在對一個集合對象進(jìn)行遍歷操作時蓖谢,你該思考一下是否可以使用map, filter或者reduce函數(shù)來替代捂蕴。
以下是總結(jié)了以下map, filter, reduce的特性:
- map返回了一個結(jié)果集,該集合中包含的所有元素是來于對源數(shù)組中每一個元素進(jìn)行相同的轉(zhuǎn)換之后形成的新元素闪幽。
- filter返回一個結(jié)果集啥辨,該集合包含的元素是源數(shù)組中的每一個符合篩選條件的元素。
- reduce返回一個值盯腌,該值是對初始值和集合中的每個元素調(diào)用閉包中相同的操作生成的溉知。