CollectionType Map
在CollectionType的extension中map方法的定義:
extension CollectionType {
/// Return an `Array` containing the results of mapping `transform`
/// over `self`.
///
/// - Complexity: O(N).
@warn_unused_result
@rethrows public func map<T>(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
...
}
@warn_unused_result:表示如果沒(méi)有檢查或者使用該方法的返回值型诚,編譯器就會(huì)報(bào)警告官边。
@noescape:用在函數(shù)的閉包參數(shù)上瓶竭,意味著這個(gè)參數(shù)是唯一可被調(diào)用的(或者用在函數(shù)調(diào)用時(shí)以參數(shù)的方式出現(xiàn)),其意思是它的生命周期比函數(shù)調(diào)用的周期短洛搀,這有助于一些小小的性能優(yōu)化,但最重要的是它屏蔽了閉包中對(duì)self.的需求佑淀。這使得函數(shù)的控制流比其他更加透明留美。
throws:可以拋出一個(gè)錯(cuò)誤的函數(shù)或方法必需使用 throws 關(guān)鍵字標(biāo)記。這些函數(shù)和方法被稱(chēng)為拋出異常函數(shù)(throwing fu nctions)和拋出異常方法(throwing methods)伸刃。
rethrows:一個(gè)函數(shù)或方法可以使用 rethrows 關(guān)鍵字來(lái)聲明,從而表明僅當(dāng)這個(gè)函數(shù)或方法的一個(gè)函數(shù)參數(shù)拋出錯(cuò)誤時(shí)這個(gè)函數(shù)或方法才拋出錯(cuò)誤谎砾。這些函數(shù)和方法被稱(chēng)為重拋出異常函數(shù)(rethrowing functions)和重拋出異常方法(rethrowing methods)。重拋出異常函數(shù)或方法必需有至少一個(gè)拋出異常函數(shù)參數(shù)捧颅。
Generator:提到數(shù)組我們就會(huì)想到遍歷景图,一般的遍歷可能都是從頭到尾進(jìn)行的。但是如果你有特殊的需求呢碉哑。你可能不想呆板的進(jìn)行遍歷挚币。這時(shí)候Generators
就可以派上用場(chǎng)了。Generators的存在是進(jìn)行特殊癖好的數(shù)組遍歷扣典,其篩選出符合該癖好的下標(biāo)索引到數(shù)組沒(méi)有元素為止妆毕。Self.Generator.Element
就是在遍歷的元素。
簡(jiǎn)化一下map的定義:
func map<T>(transform: (Self.Generator.Element) -> T) -> [T]
可以看到激捏,map 方法返回的是一個(gè)數(shù)組设塔,其獲取一個(gè)閉包表達(dá)式作為唯一參數(shù),集合中的每個(gè)元素調(diào)用一次該閉包函數(shù)远舅,并返回該元素所映射的值(也可以是不同類(lèi)型的值)闰蛔。具體的映射方式和返回值類(lèi)型由閉包來(lái)指定。
看幾個(gè)簡(jiǎn)單例子:
// 例子1:對(duì)一個(gè)Int類(lèi)型數(shù)組的元素進(jìn)行2倍放大图柏。如:[1,2,3]->[2,4,6]序六。
let arr = [1,2,3]
let doubled = arr.map{
$0 * 2
}
print(doubled)
// 輸出:[2,4,6]
// 例子2:用一個(gè)Int類(lèi)型數(shù)組存儲(chǔ)商品金額,想把每個(gè)金額后面添加一個(gè)字符“¥”蚤吹,把數(shù)組轉(zhuǎn)成字符串?dāng)?shù)組例诀。如:[10,20,30,40] -> ["10¥","20¥","30¥","40¥"]
let moneyArray = [10,20,30,40]
let stringsArray = moneyArray.map{
"\($0)¥"
}
print(stringsArray)
// 輸出:["10¥","20¥","30¥","40¥"]
// 例子3: 將Int類(lèi)型數(shù)組轉(zhuǎn)換為包含對(duì)應(yīng)String類(lèi)型的數(shù)随抠。如:[16,58,510] -> ["OneSix", "FiveEight", "FiveOneZero"]。
let digitNames = [
0: "Zero",1: "One", 2: "Two",3: "Three", 4: "Four",
5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]
let strings = numbers.map{
(var number) -> String in
var output = ""
while number > 0 {
output = digitNames[number % 10]! + output
number /= 10
}
return output
}
print(strings)
// 輸出:["OneSix", "FiveEight", "FiveOneZero"]
想要了解更多map,看這里Why coding like This ------ Map 函數(shù)揭秘
Optional Map
以下內(nèi)容出自《Swifter》
假設(shè)要將某個(gè)Int?
乘以2繁涂,一個(gè)合理的策略是如果這個(gè)Int?
有值的話拱她,就取出值進(jìn)行乘以2的操作,如果是nil
賦給結(jié)果扔罪。代碼如下:
let num: Int? = 3
var result: Int?
if let realNum = num {
result = realNum * 2
} else {
result = nil
}
其實(shí)我們有更優(yōu)雅簡(jiǎn)潔的方式秉沼,那就是使用Optional的map
。對(duì)的矿酵,不僅僅在Array或者說(shuō)CollectionType里可以用map
唬复,如果我們仔細(xì)看過(guò)Optional的聲明的話,會(huì)發(fā)現(xiàn)它也有一個(gè)map
方式:
public enum Optional<Wrapped> : _Reflectable, NilLiteralConvertible {
...
/// If `self == nil`, returns `nil`. Otherwise, returns `f(self!)`.
@warn_unused_result
@rethrows public func map<U>(@noescape f: (Wrapped) throws -> U) rethrows -> U?
...
}
這個(gè)方法能讓給我們很方便的對(duì)一個(gè)Optional值做變化和操作全肮,而不必進(jìn)行手動(dòng)的解包工作敞咧。輸入會(huì)被自動(dòng)用類(lèi)似Optional Binding的方式進(jìn)行判斷,如果有值辜腺,則進(jìn)入f
的閉包進(jìn)行變化休建,并返回一個(gè)U?
;如果輸入就是nil
的話,則直接返回nil
的U?
评疗。
有了這個(gè)方法丰包,上面的代碼就可以大大簡(jiǎn)化,而且result
甚至可以使用常量值:
let num: Int? = 3
let result = num.map{
$0 * 2
}
// result 為 {Some 6}