Swift 讀書筆記(ㄧ)
Connections
- Array
- Array with closure
- Dictionary
- Set
Array
我們要如何創建一個Array呢
有三種方法可以創建一個空Array
var array: Array<Int> = Array<Int>()
var array: [Int] = []
var array1: = array
也可以創建時同時賦與初始值
var threeInts = [Int](repeating: 1, count:3)
// [1, 1, 1]
var ints = [1, 2, 3]
// [1, 2, 3]
var mergeArray = threeInts + ints
// [1, 1, 1, 1, 2, 3]
當然我們也可以像Objective-C一樣使用count 來知道有幾個元素
也可以用isEmpty 來查詢array是否為空
mergeArray.count // 6
mergeArray.isEmpty // false
基本上,在swift 中, 我們不建議直接使用索引值去取值,例如
mergeArray[2] // 1
我們可以使用
type(of: mergeArray) // Array<Int>.Type
他回傳的是一個Array type 而不是optional type
回傳 optional type 代表的意思是查找不到時會回傳為 nil
這是一個swift保護的措施。
回傳直接的type代表他取不到想要的值時,程式會直接崩潰。
array 的 remove(at:) , removeLast() 都是這種,
也代表你要自行保證使用Array 安全,要移除最後一個元素應該優先使用popLast()。
遍歷Array
我們有三種方式可以遍歷各種Connection 或Sequence
for in
for element in mergeArray {
print(element)
}
for tulpe in array.enumerated()
for (inx, value) in mergeArray.enumerated() {
print("\(idx) : \(value)")
}
array.forEach { closure }
merge.forEach { print($0) }
Different With Array and NSArray
簡單講兩個差別就是
Swift中,可不可變數組是用let var 關鍵字聲名
Objective-C中,是以NSArray, NSMutableArray 決定
Swift中,如果你複製了一個Array,他使用一個叫做copy on write的基制,只在你再次修改Array時,他才會執行copy這個動作。
ex:
var a = [1, 2, 3]
let b = a
a.append(4)
//a [1, 2, 3, 4]
//b [1, 2, 3]
//實際可以下斷點看pointer
Objectve-C中,如果把一個NSMutableArray賦值給一個新的NSArray
這時去修改原本Array,新的Array中的元素也會跟著改變,因為NSArray中元素是引用關係的。
ex:
let a = NSMutableArray(array: [1, 2, 3])
let copyB = a
a.insert(10, at:0)
//a and copyB = [10, 1, 2, 3]
要真的讓想到Array不同時m需要使用copy 關鍵字
let copyC = a.copy() as! NSArray
但是注意,裡面的element 還是指向同一個pointer,(詳情可以去看之前講deepCopy的文章
Array with closure
前面說過,針對Array操作,使用subScript和C語言中的for loop都不是好的選擇。Swift有一套自己的方法就是使用closure操作數組。
假設我們有個數組,想要計算每個值的平方該怎麼做呢,可能會這樣寫
var array = [1, 2, 3, 4, 5]
var squares = [Int]()
for value in array {
squares.append(value * value)
}
print(squares) // [1, 4, 9, 16, 25]
我們可以使用map 函數
let squares = array.map {$0 * $0}
map 函數並不是什麼難懂的東西,它無非就是把for循環中的邏輯,封裝在一個函數裡,並返回一個新的。
Swift library中已經為我們準備許多好用的函數
array.min() // 1 optional type
array.max() // 5 optional type
array.filter { $0 * 2 == 1} // [1, 3, 5]
//只返回條件為true時
array.elementEqual([1, 2, 3], by: {$0 == $1})
// false $0 代表array的元素, $1 代表[1, 2, 3]中的元素
array.starts(with: [1, 2, 3], by: {$0 == $1})
//true
array.sorted() , array,sorted(by: >)
array.reduce(0, +) //15 0代表除了array外帶入的初始值計算
swift中Array並沒有惕除元素中的方法,我們可以自己寫一個extension
extension Array {
func reject(_ clousre: (Element) -> Bool) -> [Element] {
return filter { !closure($0)
}
}
array.reject { $0 % 2 == 0} // [1, 3, 5]
flatMap
flatMap這函數用處就是如果你使用map中的closure不返回一個數組元素,而是也返回一個數組, 這樣你就會得到一個二階陣列,這顯然不是我們需要的,這時flatMap就派上用唱
let animals = ["cat", "dog", "pig"]
let ids = [1, 2, 3]
let aa = animals.map { (ani) -> [(String,Int)] in
let bb = ids.map({ (id) -> (String,Int) in
return (ani, id)
})
return bb
}
簡化如下
animals.map {animal in
return ids.map {id in (animal, id)}
}
// [[("cat", 1), ("cat", 2), ("cat", 3)], [("dog", 1), ("dog", 2), ("dog", 3)], [("pig", 1), ("pig", 2), ("pig", 3)]]
改成
animals.flatMap {animal in
return ids.map {id in (animal, id)}
}
//[("cat", 1), ("cat", 2), ("cat", 3), ("dog", 1), ("dog", 2), ("dog", 3), ("pig", 1), ("pig", 2), ("pig", 3)]
Dictionary
其實dictionary 相關操作跟Objective-C差不多就不多講。
值得注意的是要當Dictionary的key必須是可以計算hash()的。例如Int, String, Float, Double, Bool, Date … 等等
如果是我們custom的 struct呢,swift都是通過protocol去遵從某些規格,所以我們要遵循HashAble protocol
假設我們有如下struct
struct Profile {
var name: String
var height: Int
}
let profile = Profile(name :"Jack", height: 170)
let person:[Profile: Int] = [profile: 300] // error Profile does not conform to protocol 'Hashable'
要解決這也很簡單,幫Profile加一個extension 並遵從Hashable
extension Profile:Hashable {
var hashValue: Int {
return name.hashValue ^ height.hashValue
}
}
解決了後,編譯器又提示我們沒有遵從Equatable protocol 我們把上面的extension改成
extension Profile:Hashable,Equatable {
var hashValue: Int {
return name.hashValue ^ height.hashValue
}
static func == (lhs: Profile, rhs: Profile) -> Bool {
return lhs.name == rhs.name && lhs.height == rhs.height
} // 在swift中, 運算符必須要定義成static 方法
}
這樣,我們自定義的struct就可以放進Dictionary 中當key用了。
Set 懶的寫了 囧….