看了下自己的文章記錄鸠澈,距離上次文章已經(jīng)快兩個(gè)月,距第一篇文章已經(jīng)有快5個(gè)月了层释。本以為自己有了寫(xiě)技術(shù)文章的這個(gè)好習(xí)慣婆瓜,沒(méi)想到還是因?yàn)槟承┮蛩貨](méi)能堅(jiān)持,比如帶項(xiàng)目 =贡羔。= ...
本來(lái)的開(kāi)發(fā)組長(zhǎng)當(dāng)?shù)暮煤玫牧祝讯∽屛胰ы?xiàng)目,還沒(méi)產(chǎn)品經(jīng)理乖寒。我一個(gè)人又要出原型猴蹂,想交互,還要管理團(tuán)隊(duì)楣嘁,真的是mmp喲磅轻。幸虧UI說(shuō)你直接草圖給我就好,幸虧Axure簡(jiǎn)單功能不難逐虚,幸虧storyboard和設(shè)計(jì)工具一樣都能出圖聋溜。要不是想著帶項(xiàng)目能讓我成長(zhǎng),我才不干咧痊班!
前言說(shuō)完了勤婚,因?yàn)轫?xiàng)目需要,面試了好多個(gè)iOS涤伐,發(fā)現(xiàn)自身有些不足馒胆,并且非科班出身所以基礎(chǔ)知識(shí)也(ji)不(hu)牢(mei)固(you)。然后網(wǎng)上找了下swift進(jìn)階的書(shū)凝果,看到了《Swift進(jìn)階》這本書(shū)祝迂,喵神翻譯的,而且今年5月才發(fā)售器净,價(jià)值連城啊型雳,立馬上某東買(mǎi)去。順便下載了一個(gè)《Effective Objective-C 2.0 編寫(xiě)高質(zhì)量iOS與OS X代碼的52個(gè)有效方法》.pdf
項(xiàng)目二期結(jié)束了,我決定開(kāi)始我的Swift進(jìn)階之旅纠俭。順便做個(gè)記錄沿量,監(jiān)督自己
每次的記錄我都會(huì)寫(xiě)一些書(shū)里的重點(diǎn)內(nèi)容和相關(guān)的文章。
2017.07.31
結(jié)構(gòu)體和枚舉是值類(lèi)型冤荆,引用是一種特殊類(lèi)型的值朴则,==有時(shí)候被稱(chēng)為結(jié)構(gòu)相等,而===則被稱(chēng)為指針相等或者引用相等钓简。
Swift3.0 - 類(lèi)和結(jié)構(gòu)體的區(qū)別
Swift 中的枚舉乌妒,你應(yīng)該了解的東西
2017.08.01
什么? 朕的大清亡了外邓?撤蚊??
公司解散你敢信损话?其他部門(mén)遭遇嚴(yán)重生產(chǎn)事故侦啸,公司整體解散,只留骨干整體進(jìn)入其他技術(shù)公司席镀。我的天匹中,第一次遭遇公司解散夏漱,簡(jiǎn)直就是
無(wú)心擼代碼豪诲,玩爐石去了。
2017.08.02
生活還是要繼續(xù)啊挂绰,很開(kāi)心我又開(kāi)始做開(kāi)發(fā)了屎篱,項(xiàng)目還是要繼續(xù)的。只不過(guò)不用我?guī)Э伲膊挥梦蚁胄枨罅耍ㄟ@一點(diǎn)我還是很開(kāi)心的)交播。雖然帶項(xiàng)目才兩個(gè)月的時(shí)間,雖然這種短暫的經(jīng)歷不一定會(huì)對(duì)技能樹(shù)有(mei)影(bian)響(hua)践付,但是也算一個(gè)經(jīng)歷咯秦士。
引用是一種特殊類(lèi)型的值:它是一個(gè)“指向”另一個(gè)值的值。對(duì)于一個(gè)類(lèi)的實(shí)例永高,我們只能在變量里持有對(duì)它的引用隧土,然后使用這個(gè)引用來(lái)訪問(wèn)它窄俏。
class Person {
var name:String!
init(name:String){
self.name = name
}
}
let person1 = Person.init(name: "Bart")
person1.name
let person2 = Person.init(name: "Lisa")
person2.name
代碼里person1和person2指向同一個(gè)地址辰狡,而.name的內(nèi)容卻是不一樣的。
兩個(gè)引用可能會(huì)指向同一個(gè)值狭莱,這引入了一種可能性饲宛,那就是這個(gè)值可能會(huì)被程序的兩個(gè)不同的部分所改變皆愉。
Swift 風(fēng)格指南
https://swift.org/documentation/api-design-guidelines/
對(duì)于代碼編寫(xiě)原則,我將簡(jiǎn)單明了,并且常用的原則整理出來(lái)幕庐。
- 務(wù)必為函數(shù)添加文檔注釋——特別是泛型函數(shù)久锥。
- 類(lèi)型使用大寫(xiě)字母開(kāi)頭,函數(shù)异剥,變量和枚舉成員使用小寫(xiě)字母開(kāi)頭奴拦,兩者都使用駝峰式命名法。
- 優(yōu)先選擇結(jié)構(gòu)體届吁,只在確實(shí)需要使用到類(lèi)特有的特性或者是引用語(yǔ)義時(shí)才使用類(lèi)错妖。
- 除非你的設(shè)計(jì)就是希望某個(gè)類(lèi)被繼承使用,否則都應(yīng)該將它們標(biāo)記為final疚沐。
- 使用guard來(lái)提早退出的方法暂氯。
- 不要寫(xiě)重復(fù)的代碼。如果你發(fā)現(xiàn)你寫(xiě)了好幾次類(lèi)似的代碼片段亮蛔,那么試著將它們提取到一個(gè)函數(shù)里痴施,并且考慮將這個(gè)函數(shù)轉(zhuǎn)化為協(xié)議擴(kuò)展的可能性。
內(nèi)建集合類(lèi)型
數(shù)組
數(shù)組是一系列相同類(lèi)型的元素的有序的容器
var x = [1,2,3]
var y = x
y.append(4)
x
//x不會(huì)發(fā)生改變
//不想讓b發(fā)生改變究流,但是任然被a影響
let a = NSMutableArray.init(array: [1, 2, 3])
let b:NSArray = a
a.insert(4, at: 3) //[1, 2, 3, 4]
b //[1, 2, 3, 4]
//不想讓d發(fā)生改變辣吃, 正確方法
let c = NSMutableArray.init(array: [1, 2, 3])
let d = c.copy() as! NSArray
c.insert(4, at: 3) //[1, 2, 3, 4]
d //[1, 2, 3]
Swift標(biāo)準(zhǔn)庫(kù)中的所有集合類(lèi)型都使用了“寫(xiě)時(shí)復(fù)制”這一技術(shù),它能夠保證只在必要的時(shí)候?qū)?shù)據(jù)進(jìn)行復(fù)制芬探。在我們的例子中神得,直到y(tǒng).append被調(diào)用之前,x和y都將共享內(nèi)部的存儲(chǔ)偷仿。
2017.08.03
數(shù)組變形
一些數(shù)組的方法
mutabFibs //[0, 1, 1, 2, 3, 5, 8, 13, 21]
var new = [Int]()
//去掉數(shù)組首個(gè)元素
for value in mutabFibs.dropFirst(){
new.append(value)
}
new //[1, 1, 2, 3, 5, 8, 13, 21]
var new1 = [Int]()
//去掉數(shù)組后6個(gè)元素
for value in mutabFibs.dropLast(6){
new1.append(value)
}
new1 //[0, 1, 1]
var new2 = [Int]()
// 如果越界new2會(huì)是空數(shù)組
for value in mutabFibs.dropLast(10){
new2.append(value)
}
new2
//遍歷元素和對(duì)應(yīng)的下標(biāo)
for (index, value) in mutabFibs.enumerated(){
print("index:\(index) value:\(value)")
}
數(shù)組的map方法
let math = [2,4,6,8]
var squared:[Int] = []
//把數(shù)組中的數(shù)字平方
for value in math{
squared.append(value * value)
}
squared //[4, 16, 36, 64]
let squared1 = math.map({num in num * num}) //不知道為什么會(huì)循環(huán)5次
squared1 //[4, 16, 36, 64]
//new.map({})
extension Array{
func map<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
result.reserveCapacity(count)
for x in self{
result.append(transform(x))
}
return result
}
}
//刪選出數(shù)組里大于10的元素
let filter = mutabFibs.filter { $0 > 10 }
filter //[13, 21]
//刪選出數(shù)組里大于3的元素
let test = math.filter { (tt) -> Bool in
return tt > 3
}
test //[4, 6, 8]
上面關(guān)于Array的擴(kuò)展是map函數(shù)可能的一種實(shí)現(xiàn)方式
Element是數(shù)組中包含的元素類(lèi)型占位符哩簿,T是元素轉(zhuǎn)換之后的類(lèi)型的占位符。
關(guān)于.filter酝静,我的理解就是對(duì)于你的需要节榜,返回true就保留這個(gè)元素,返回false就棄掉這個(gè)元素
let names = ["Paula", "Elena", "Zoe"]
var lastNameEndingInA: String?
//反向遍歷出名字中帶有a的最早的元素(找出就終止循環(huán))
for name in names.reversed() where name.hasSuffix("a") {
lastNameEndingInA = name
break
}
lastNameEndingInA // Optional("Elena")
//反向遍歷 .reversed()
for na in names.reversed(){
if na.hasSuffix("a"){
print(na) //Elena
//Paula
}
}
extension Sequence{
func last(where predicate: (Iterator.Element) -> Bool) -> Iterator.Element? {
for element in reversed() where predicate(element){
return element
}
return nil
}
}
let match = names.last(where: { $0.hasSuffix("a") })
match
哎别智,今天就到這兒了宗苍。大神的高階函數(shù)寫(xiě)法是真的高,小弟受教了氨¢弧讳窟!
2017.08.04
可變和帶有狀態(tài)的閉包
extension Array {
func accumulate<Result>(_ initialResult: Result,_ nextPartial:(Result, Element) -> Result) -> [Result]{
var running = initialResult
return map({ (next) -> Result in
print("before:\(running)")
print("next:\(next)")
running = nextPartial(running, next)
print("after running:\(running)")
return running
})
}
}
var numArray = [5,16,23,44]
let acc = numArray.accumulate(3, +)
acc //[8, 24, 47, 91]
let error = numArray.accumulate(3) { (count, num) -> Int in
return count * num
}
error //[15, 240, 5520, 242880]
var char = ["boy", "girl", "children"]
let ttt = char.accumulate("bad", +)
ttt //["badboy", "badboygirl", "badboygirlchildren"]
let errorStr = char.accumulate("god") { (first, str) -> String in
return "\(first) \(str)"
}
errorStr //["god boy", "god boy girl", "god boy girl children"]
extension String{
func addtest<T>(objc:(String, Int) -> T) -> T{
let tt = objc(self, 4)
return tt
}
}
var four = "four is "
let ff = four.addtest { (str, num) -> String in
return str + "\(num)"
}
ff
我昨天就開(kāi)始試圖讀懂這個(gè)了,就是不明白I呤挪钓!尤其是我回車(chē)讓方法自動(dòng)展開(kāi),完全不知道方法nextPartial:(Result, Element) -> Result
是怎么可以放+號(hào)的耳舅。running = nextPartial(running, next)
更不用說(shuō)這里為什么會(huì)自動(dòng)根據(jù)傳過(guò)來(lái)的符號(hào)就開(kāi)始運(yùn)算了碌上。let acc = numArray.accumulate(3, +)
這個(gè)加號(hào)看得我這種初級(jí)程序員一臉懵逼倚评,傳遞(Result,Element)
類(lèi)型并得到Result
類(lèi)型的返回值的函數(shù)是怎么簡(jiǎn)寫(xiě)成+就結(jié)束了,+號(hào)怎么傳遞過(guò)去讓程序知道你想進(jìn)行相加操作的呢馏予? 我擴(kuò)展開(kāi)是需要自己在返回值的時(shí)候去定義加減乘除讓程序知道的天梧。
哎,最后拓展了個(gè)方法試圖讓自己明白這個(gè)+號(hào)霞丧,發(fā)現(xiàn)還是不知道如何簡(jiǎn)寫(xiě)成那樣呢岗。望看到的大指點(diǎn)指點(diǎn)我。
filter會(huì)創(chuàng)建一個(gè)全新的數(shù)組
var filterArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let fl = filterArray.filter({ $0 % 2 == 0})
fl //[2, 4, 6, 8, 10]
let f2 = filterArray.filter { (num) -> Bool in
return num % 2 == 0
}
f2 //[2, 4, 6, 8, 10]
let sq = (1..<10).map { $0 * $0 }.filter { (num) -> Bool in
return num % 6 == 0
}
sq //[2, 4, 6, 8, 10]
extension Array {
func filter(_ isIncluded: (Element) -> Bool) -> [Element] {
var result: [Element] = []
for x in self where isIncluded(x) {
print("==\(x)==")
print(isIncluded(x))
result.append(x)
}
return result
}
}
let fibs = [1, 2, 3, 4, 5]
//Reduc
var total = 0
for num in fibs {
total = total + num
}
total //15
let sum = fibs.reduce(0, {total, num in total + num})
sum //15
//我現(xiàn)在理解是消消樂(lè)蛹尝,相同的參數(shù)抵消后豫,留下了運(yùn)算符
let sum1 = fibs.reduce(0, +)
sum1 //15
let sum2 = fibs.reduce(0) { (total, num) -> Int in
return total + num
}
sum2 //15
//reduc實(shí)現(xiàn)
extension Array {
func reduce<Result>(_ initialResult: Result,
_ nextPartialResult: (Result, Element) -> Result) -> Result
{
var result = initialResult
for x in self {
result = nextPartialResult(result, x)
}
return result
}
}
后面看到flatMap舉得例子有點(diǎn)繞,待我看懂分析好了再與諸君分享突那。
看書(shū)真的是枯燥啊挫酿,共勉之!
2017.08.05
flatMap
有時(shí)候我們會(huì)想要對(duì)一個(gè)數(shù)組用一個(gè)函數(shù)進(jìn)行map愕难,但是這個(gè)變形函數(shù)返回的是另一個(gè)數(shù)組早龟,而不是單獨(dú)的元素。
//內(nèi)部實(shí)現(xiàn)
extension Array {
func flatMap<T>(_ transform: (Element) -> [T]) -> [T] {
var result: [T] = []
for x in self {
print("objc:\(x)")
result.append(contentsOf: transform(x))
print("result:\(result)")
}
return result
}
}
let suits = ["?", "?", "?", "?"]
let ranks = ["J","Q","K","A"]
let result = suits.flatMap { suit in
ranks.map { rank in
(suit, rank)
}
}
result //[("?", "J"), ("?", "Q"), ("?", "K"), ("?", "A"), ("?", "J"), ("?", "Q"), ("?", "K"), ("?", "A"), ("?", "J"), ("?", "Q"), ("?", "K"), ("?", "A"), ("?", "J"), ("?", "Q"), ("?", "K"), ("?", "A")]
//flatMap示例
let test = ranks.flatMap { (str) -> [String] in
return ["test", str]
}
test //["test", "J", "test", "Q", "test", "K", "test", "A"]
//拆解出ranks.map
let test1 = ranks.map { (rank) -> (String, String) in
return ("test", rank)
}
test1 //[(.0 "test", .1 "J"), (.0 "test", .1 "Q"), (.0 "test", .1 "K"), (.0 "test", .1 "A")]
//組合猫缭, 省調(diào)返回值聲明和return可以由系統(tǒng)自動(dòng)判斷葱弟,簡(jiǎn)化了很多。
let result2 = suits.flatMap { (hua) -> [(String, String)] in
return ranks.map({ (char) -> (String, String) in
return (hua, char)
})
}
result2 //[("?", "J"), ("?", "Q"), ("?", "K"), ("?", "A"), ("?", "J"), ("?", "Q"), ("?", "K"), ("?", "A"), ("?", "J"), ("?", "Q"), ("?", "K"), ("?", "A"), ("?", "J"), ("?", "Q"), ("?", "K"), ("?", "A")]
結(jié)果很長(zhǎng)猜丹,我也有注釋在代碼里芝加,就不上截圖了。
使用forEach進(jìn)行迭代
var numbers = [1, 2, 3, 4]
for value in numbers{
print(value)
}
numbers.forEach { (value) in
print("forEach: \(value)")
}
for循環(huán)和forEach在某些情況能達(dá)到同樣的效果居触,而且forEach代碼更簡(jiǎn)潔妖混。不過(guò)
for 循環(huán)和 forEach 有些細(xì)微的不同老赤,值得我們注意轮洋。比如,當(dāng)一個(gè) for 循環(huán)中有 return 語(yǔ)句時(shí)抬旺,將它重寫(xiě)為 forEach 會(huì)造成代碼行為上的極大區(qū)別弊予。
再思考一下下面這個(gè)簡(jiǎn)單的例子:
(1..<10).forEach { number in
print(number)
if number > 2 { return }
}
你可能一開(kāi)始還沒(méi)反應(yīng)過(guò)來(lái),其實(shí)這段代碼將會(huì)把輸入的數(shù)字全部打印出來(lái)开财。return 語(yǔ)句并不會(huì)終止循環(huán)汉柒,它做的僅僅是從閉包中返回。
書(shū)里有個(gè)更復(fù)雜的例子的對(duì)比责鳍,我沒(méi)整理碾褂,到是覺(jué)得里面這個(gè)方法可以仔細(xì)研究一下
numbers.indices //CountableRange(0..<4)
extension Array where Element: Equatable {
func index(of element: Element) -> Int? {
print(element)
for idx in self.indices where self[idx] == element {
return idx
}
return nil
}
}
numbers.index(of: 3) //2 下標(biāo)2
numbers.index(of: 4) //3 下標(biāo)3
numbers.index(of: 5) //nil 找不到這個(gè)數(shù)字的下標(biāo)
var strs = ["一","二","三"]
strs.index(of: "三") //2 下標(biāo)2
strs.index(of: "四") //nil 找不到這個(gè)字符串的下標(biāo)
題外話:看到跌代,突然就想了解下這個(gè)名詞历葛,然后看到遞歸和迭代正塌,然后看到一個(gè)好的例子
//迭代實(shí)現(xiàn)斐波那契數(shù)列
func fab_iteration(index:Int) -> Int{
guard index > 0 else {
return 0
}
if index == 1 || index == 2 {
return 1
}else{
var f1 = 1
var f2 = 1
var f3 = 0
for num in 0..<index - 2 {
f3 = f1 + f2
f1 = f2
f2 = f3
}
return f3
}
}
fab_iteration(index: 0)
fab_iteration(index: 1)
fab_iteration(index: 2)
fab_iteration(index: 3)
fab_iteration(index: 4)
fab_iteration(index: 11)
fab_iteration(index: 12)
fab_iteration(index: 13)
//遞歸實(shí)現(xiàn)斐波那契數(shù)列
func fab_recursion(index:Int) -> Int{
guard index > 0 else {
return 0
}
if index == 1 || index == 2{
return 1
}else{
return fab_recursion(index: index - 1) + fab_recursion(index: index - 2) //遞歸求值嘀略,自己調(diào)用自己
}
}
fab_recursion(index: 0)
fab_recursion(index: 1)
fab_recursion(index: 2)
fab_recursion(index: 3)
fab_recursion(index: 4)
fab_recursion(index: 11)
fab_recursion(index: 12)
fab_recursion(index: 13)
看起來(lái)遞歸更簡(jiǎn)潔了,但是我上截圖你們就知道區(qū)別了乓诽。
迭代運(yùn)行了33次帜羊,遞歸466次,這個(gè)就相差太多了鸠天,也就是遞歸吃了你超級(jí)多的內(nèi)存讼育。
總結(jié)就是:能自己內(nèi)部實(shí)現(xiàn),麻煩一點(diǎn)也要用迭代稠集。實(shí)在無(wú)法自己內(nèi)部實(shí)現(xiàn)才用遞歸奶段。
數(shù)組類(lèi)型
切片
var fibs = [0, 1, 1, 2, 3, 5, 8]
type(of: fibs) //Array<Int>.Type
let slice = fibs[1..<fibs.endIndex]
slice //[1, 1, 2, 3, 5, 8]
type(of: slice) //ArraySlice<Int>.Type 返回?cái)?shù)組的一個(gè)切片(slice)
切片類(lèi)型只是數(shù)組的一種表示方式,它背后的數(shù)據(jù)仍然是原來(lái)的數(shù)組
也就是相對(duì)于原數(shù)組剥纷,它只不過(guò)是從第一個(gè)數(shù)據(jù)開(kāi)始展示忧饭,本質(zhì)上任然是之前的數(shù)組
如果要轉(zhuǎn)換為數(shù)組,就需要構(gòu)建成數(shù)組
//構(gòu)成數(shù)組
let slicceArray = Array(fibs[1..<fibs.endIndex])
type(of: slicceArray) //Array<Int>.Type
2017.08.07
字典
在一個(gè)字典中筷畦,每個(gè)鍵都只能出現(xiàn)一次词裤。通過(guò)鍵來(lái)獲取值所花費(fèi)的平均時(shí)間是常數(shù)量級(jí)的 (作為對(duì)比,在數(shù)組中搜尋一個(gè)特定元素所花的時(shí)間將與數(shù)組尺寸成正比)鳖宾。和數(shù)組有所不同吼砂,字典是無(wú)序的,使用 for 循環(huán)來(lái)枚舉字典中的鍵值對(duì)時(shí)鼎文,順序是不確定的渔肩。
enum Setting {
case text(String)
case int(Int)
case bool(Bool)
}
let defaultSettings: [String:Setting] = ["Airplane Mode": Setting.bool(true), "Name": Setting.text("My iPhone"), "PhoneNumber":Setting.int(110)]
defaultSettings["Name"] //text("My iPhone")
defaultSettings["test"] //nil
var defaultSettings2 = defaultSettings
defaultSettings2.removeValue(forKey: "Name") //text("My iPhone") 返回了被刪除的值
defaultSettings2["Name"] //text("My iPhone")
defaultSettings2.updateValue(Setting.int(12110), forKey: "PhoneNumber") //int(110) 返回了更新前的值
defaultSettings2["PhoneNumber"] //int(12110)
defaultSettings2.updateValue(.text("new"), forKey: "new value") //nil 如果之前沒(méi)值則返回nil
defaultSettings2["new value"] //text("new") 新的值
有用的字典擴(kuò)展
//合并兩個(gè)字典,通過(guò)循環(huán)添加內(nèi)容
extension Dictionary {
mutating func merge<S>(_ other: S) where S: Sequence, S.Iterator.Element == (key: Key, value: Value) {
for (k, v) in other {
self[k] = v
}
}
}
defaultSettings2.merge(["1":.text("111")])
var set = ["a":"1","b":"2"]
set.merge(["c":"3", "d":"4"])
//從序列創(chuàng)建數(shù)組的方法
extension Dictionary {
init<S:Sequence>(_ sequence: S) where S.Iterator.Element == (key: Key, value: Value){
self = [:]
self.merge(sequence)
}
}
let se = Dictionary(set)
se
type(of: se)
//字典的map方法拇惋,會(huì)返回?cái)?shù)組
let seMap = se.map { (key: String, value: String) -> (String, String) in
if key == "a"{
return ("is a :" + key, "is 1 :" + value)
}else{
return (key + "lala", value + "map")
}
}
//字典調(diào)用map放回會(huì)返回?cái)?shù)組
type(of: seMap) //Array<(String, String)>.Type
//返回字典的自定義map函數(shù)
extension Dictionary {
func mapValues<NewValue>(transform: (Value) -> NewValue)
-> [Key:NewValue] {
return Dictionary<Key, NewValue>(map { (key, value) in
print("key:\(key) value:\(transform(value))")
return (key, transform(value))
})
}
}
let settingsAsStrings = defaultSettings2.mapValues { setting -> String in
switch setting {
case .text(let text):
return text
case .int(let number):
return String(number)
case .bool(let value):
return String(value)
}
}
settingsAsStrings //["PhoneNumber": "12110", "new value": "new", "Airplane Mode": "true", "1": "111"]
//簡(jiǎn)單示例
let mama = se.mapValues { (str) -> String in
return str + " mapValues"
}
mama //["b": "2 mapValues", "a": "1 mapValues", "d": "4 mapValues", "c": "3 mapValues"]
代碼注釋很詳細(xì)周偎,而且有之前的數(shù)組方法做鋪墊,理解起來(lái)容易多了撑帖。
2017.08.08
Set
集合是一組無(wú)序的元素蓉坎,每個(gè)元素只會(huì)出現(xiàn)一次。
//集合
let naturals: Set = [1, 2, 3, 2]
naturals //[2,3,1]
naturals.contains(3) //true
naturals.contains(2) //true
naturals.contains(4) //false
集合代數(shù)
//一個(gè)集合中求另一個(gè)集合的補(bǔ)集:
let iPods: Set = ["iPod touch", "iPod nano", "iPod mini","iPod shuffle", "iPod Classic"]
let discontinuedIPods: Set = ["iPod mini", "iPod Classic"]
let currentIPods = iPods.subtracting(discontinuedIPods)
currentIPods // ["iPod shuffle", "iPod nano", "iPod touch"]
//求兩個(gè)集合的交集
let touchscreen: Set = ["iPhone", "iPad", "iPod touch", "iPod nano"]
let iPodsWithTouch = iPods.intersection(touchscreen)
iPodsWithTouch // ["iPod touch", "iPod nano"]
//求兩個(gè)集合的并集
var discontinued: Set = ["iBook", "Powerbook", "Power Mac"]
discontinued.formUnion(discontinuedIPods)
discontinued // ["iBook", "iPod mini", "Powerbook", "Power Mac", "iPod Classic"]
索引集合
var indices = IndexSet()
indices.insert(integersIn: 1..<5)
indices.insert(integersIn: 11..<15)
let indicesNumber = indices.filter{ $0 % 1 == 0 }
indicesNumber //[1, 2, 3, 4, 11, 12, 13, 14]
let evenIndices = indices.filter { $0 % 2 == 0 }
evenIndices // [2, 4, 12, 14]
閉包使用集合
extension Sequence where Iterator.Element: Hashable{
func unique() -> [Iterator.Element]{
var seen: Set<Iterator.Element> = []
return filter {
if seen.contains($0){
return false
}else{
seen.insert($0)
return true
}
}
}
}
let uni = [1,2,3,3,5,5,6,7,7,13,12,0].unique() //[1, 2, 3, 5, 6, 7, 13, 12, 0]
type(of: uni) //Array<Int>.Type
//示例
var test:Set<Int> = []
type(of: test) //Set<Int>.Type
let uni1 = [1,2,3,3,5,5,6,7,7,13,12,0].filter { (num) -> Bool in
if test.contains(num){
print("false:\(num)")
return false
}else{
print("true:\(num)")
test.insert(num)
return true
}
}
uni1 //[1, 2, 3, 5, 6, 7, 13, 12, 0]
type(of: uni1) //Array<Int>.Type
Range
// 0 到 9, 不包含 10
let singleDigitNumbers = 0..<10
// 包含 "z"
let lowercaseLetters = Character("a")...Character("z")
范圍看起來(lái)很自然地會(huì)是一個(gè)序列或者集合類(lèi)型胡嘿,但是可能出乎你的意料蛉艾,它并非這兩者之一 - 至少不是所有的范圍都是序列或者集合類(lèi)型。
在標(biāo)準(zhǔn)庫(kù)中衷敌,現(xiàn)在有四種范圍類(lèi)型勿侯。它們能夠被歸類(lèi)到一個(gè) 2x2 的矩陣中:
---- | 半開(kāi)范圍 | 閉合范圍 |
---|---|---|
元素滿(mǎn)足 Comparable | Range | ClosedRange |
元素滿(mǎn)足 Strideable (以整數(shù)為步長(zhǎng)) | CountableRange | CountableClosedRange |
只有半開(kāi)范圍能夠表達(dá)空區(qū)間的概念 (當(dāng)范圍的上下邊界相等時(shí),比如 5..<5)缴罗。
只有閉合范圍能夠包含它的元素類(lèi)型所能表達(dá)的最大值 (比如 0...Int.max)助琐。半開(kāi)范圍總是最少會(huì)有一個(gè)值比范圍所表達(dá)的只要大。
Range后續(xù)的內(nèi)容感覺(jué)超級(jí)底層面氓,我決定以后再看看好了兵钮,現(xiàn)在看也看不懂沟堡。
發(fā)現(xiàn)一個(gè)文章寫(xiě)完太長(zhǎng)了,分章節(jié)記載分享好了矢空,也方便有需要的人根據(jù)需求查看
《Swift進(jìn)階》王巍譯——集合類(lèi)型協(xié)議