《Swift進(jìn)階》王巍譯——內(nèi)建集合類(lèi)型

看了下自己的文章記錄鸠澈,距離上次文章已經(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

playground截圖

代碼里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]
playground截圖

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)")
    
}

playground截圖

數(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]

playground截圖

上面關(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

playground截圖

哎别智,今天就到這兒了宗苍。大神的高階函數(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
    }
    
}
playground截圖

后面看到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ū)別了乓诽。

playground截圖

迭代運(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ù)組

image.png

如果要轉(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
playground截圖

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é)議

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末航罗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子屁药,更是在濱河造成了極大的恐慌粥血,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酿箭,死亡現(xiàn)場(chǎng)離奇詭異复亏,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)缭嫡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)缔御,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人妇蛀,你說(shuō)我怎么就攤上這事耕突。” “怎么了评架?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵眷茁,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我纵诞,道長(zhǎng)上祈,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任浙芙,我火速辦了婚禮登刺,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘嗡呼。我一直安慰自己纸俭,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布晤锥。 她就那樣靜靜地躺著掉蔬,像睡著了一般。 火紅的嫁衣襯著肌膚如雪矾瘾。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,696評(píng)論 1 312
  • 那天箭启,我揣著相機(jī)與錄音壕翩,去河邊找鬼。 笑死傅寡,一個(gè)胖子當(dāng)著我的面吹牛放妈,可吹牛的內(nèi)容都是我干的北救。 我是一名探鬼主播,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼芜抒,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼珍策!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起宅倒,我...
    開(kāi)封第一講書(shū)人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤攘宙,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后拐迁,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蹭劈,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年线召,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了铺韧。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缓淹,死狀恐怖哈打,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情讯壶,我是刑警寧澤前酿,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站鹏溯,受9級(jí)特大地震影響罢维,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜丙挽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一肺孵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧颜阐,春花似錦平窘、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至肤舞,卻和暖如春紫新,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背李剖。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工芒率, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人篙顺。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓偶芍,卻偏偏與公主長(zhǎng)得像充择,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匪蟀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 集合類(lèi)型: Swift椎麦,和其他現(xiàn)代編程語(yǔ)言一樣,有內(nèi)置的集合類(lèi)型數(shù)組(Array)和字典(Dictionary)材彪,...
    小松樹(shù)先生閱讀 1,111評(píng)論 0 2
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)观挎、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,124評(píng)論 4 61
  • 前言 3月27號(hào)蘋(píng)果發(fā)布了Swift3.1查刻,官方教程也更新到了3.1键兜,查看更新記錄發(fā)現(xiàn)更新的內(nèi)容對(duì)之前的文章并沒(méi)有...
    BoomLee閱讀 3,149評(píng)論 0 4
  • 二階段,第四次作業(yè)穗泵。 《活得明白》P31頁(yè) R?閱讀原文片段 跨越選項(xiàng)看目標(biāo)普气。 當(dāng)我們不知道要去哪的時(shí)候,對(duì)路徑的...
    露蘇維閱讀 157評(píng)論 1 0
  • 1 前陣子在公眾號(hào)上看到一則新聞,說(shuō)四川有個(gè)80多歲的老太太坐車(chē)到成都看病履肃,但她的坐票沒(méi)有買(mǎi)到終點(diǎn)站所以在途中被主...
    谷棋ss閱讀 245評(píng)論 2 3