Ch17.泛型
17.1 泛型型態 兩數對調 佇列的運作 氣泡排序法
17.1.1 兩數對調 兩數對調先前已在函式那一章有討論過。程式如下: 17.1.1 兩數對調 兩數對調先前已在函式那一章有討論過。程式如下: 明明只是型態不同,但要處理不同型態的對調,卻要重新撰寫程 式,這效率太低。處理此問題與解決的方式可以使用所謂的泛型 型態的函式。 // swap two integer numbers func swapInts(a: inout Int, b: inout Int) { let temp = a a = b b = temp }
範例程式part1 // swap using generic function func swapData<T>(a: inout T, b: inout T) { let temp = a a = b b = temp } var oneInt = 100 var anotherInt = 200 print("Before swapped: ") print("oneInt = \(oneInt), anotherInt = \(anotherInt) ") swapData(a: &oneInt, b: &anotherInt) print("After swapped: ") var oneString = "Hello" var anotherString = "Swift" print("oneInt = \(oneString), anotherInt = \(anotherString) ") swapData(a: &oneString, b: &anotherString)
範例程式part2 var oneDouble = 123.456 var anotherDouble = 654.321 print("Before swapped: ") print("oneInt = \(oneDouble), anotherInt = \(anotherDouble) ") swapData(a: &oneDouble, b: &anotherDouble) print("After swapped: ")
輸出結果 Before swapped: oneInt = 100, anotherInt = 200 After swapped: oneString = Hello, anotherString = Swift oneString = Swift, anotherString = Hello oneInt = 123.456, anotherInt = 654.321 oneInt = 654.321, anotherInt = 123.456
撰寫成泛型型態函式的步驟是先將不一樣的地方畫出,然後以T表示之,並且在函 式名稱後加上 <T> 這樣就大功告成了。
17.1.2 佇列的運作 佇列 (queue) 和堆疊 (stack) 是資料結構的重要主題,在此僅以佇 列為例。 17.1.2 佇列的運作 佇列 (queue) 和堆疊 (stack) 是資料結構的重要主題,在此僅以佇 列為例。 佇列就是排隊,先來的先服務。
範例程式part1 // generic type struct Queue<T> { var items = [T]() mutating func insert(item: T) { items.append(item) } mutating func delete() -> T { return items.remove(at: 0) var queueOfInt = Queue<Int>() queueOfInt.insert(item: 100) queueOfInt.insert(item: 200) queueOfInt.insert(item: 300) queueOfInt.insert(item: 400) queueOfInt.insert(item: 500) print("The integer queue has following elements: ") for i in queueOfInt.items { print("\(i) ", terminator: "") print("")
範例程式part2 queueOfInt.delete() print("After delete 100, the queue has following elements: ") for i in queueOfInt.items { print("\(i) ", terminator: "") } print("") queueOfInt.insert(item: 600) print("After insert 600, the queue has following elements: ") print("\n")
輸出結果 The integer queue has following elements: 100 200 300 400 500 After delete 100, the queue has following elements: 200 300 400 500 After insert 600, the queue has following elements: 200 300 400 500 600
17.2 型態限制 有時在處理泛型時,需要一些條件加進來才能處理,此稱為型態 的限制 (type constraint) 。
17.2.1 找某一值位於陣列的何處 以下是一找尋某一字串在字串陣列的位置,其片段程式如 下: 同理也可以將上述的程式改為整數、浮點數陣列。 17.2.1 找某一值位於陣列的何處 以下是一找尋某一字串在字串陣列的位置,其片段程式如 下: 同理也可以將上述的程式改為整數、浮點數陣列。 func searchData(array: [String], valueToSearch: String) ->Int? { for (index, value) in array.enumerated() { if value == valueToSearch { return index } return nil
範例程式part1 func searchData<T: Equatable>(array: [T], valueToSearch : T) -> Int? { for (index, value) in array.enumerated() { if value == valueToSearch { return index } return nil let arrayofStrings = ["Apple", "Guava", "Banana", "Kiwi", "Orange"] let found = searchData(array: arrayofStrings, valueToSearch: "Kiwi") print("The index of Kiwi is \(found)") let found2 = searchData(array: arrayofStrings, valueToSearch: "Pineapple") print("The index of Pineapple is \(found2)") let arrayOfInt = [11, 22, 33, 44, 55] let found3 = searchData(array: arrayOfInt, valueToSearch: 55) print("\nThe index of 55 is \(found3)") let found4 = searchData(array: arrayOfInt, valueToSearch: 66) print("The index of 66 is \(found4)") let arrayOfDouble = [11.1, 22.2, 33.3, 44.4, 55.5] let found5 = searchData(array: arrayOfDouble, valueToSearch: 22.2)
範例程式part2 print("\nThe index of 22.2 is \(found5)") let found6 = searchData(array: arrayOfDouble, valueToSearch: 66.6) print("The index of 66.6 is \(found6)")
輸出結果 The index of Kiwi is Optional(3) The index of Pineapple is nil The index of 55 is Optional(4) The index of 66 is nil The index of 22.2 is Optional(1) The index of 66.6 is nil
17.2.2 氣泡排序 氣泡排序是兩兩相比較,若是由小由大,表示當前一個值比後一 值大時,則必須交換,否則不變動。
範例程式 //sorting integer numbers var arrOfInt = [10, 30, 5, 7, 2, 8, 18, 12] print("Before sorted: ") for i in arrOfInt { print("\(i) ", terminator: "") } func bubbleSort(arr: inout [Int]) { var flag: Bool for i in 0..<arr.count-1 { flag = false for j in 0..<arr.count-i-1 { if arr[j] > arr[j+1] { flag = true let temp = arr[j] arr[j] = arr[j+1] arr[j+1] = temp if flag == false { break bubbleSort(arr: &arrOfInt) print("\n\nAfter sorted: ") for j in arrOfInt { print("\(j) ", terminator: "") print("")
輸出結果 Before sorted: 10 30 5 7 2 8 18 12 After sorted: 2 5 7 8 10 12 18 30
17.3 關連型態 當定義協定時,有時宣告一或多個關連型態當做協定的定義很有 用。 17.3 關連型態 當定義協定時,有時宣告一或多個關連型態當做協定的定義很有 用。 一般關連型態以associatedtype關鍵字表示(Swift 3之前是 typealias)。
範例程式part1 protocol ExtraInformation { associatedtype ItemType var count: Int {get} subscript(i: Int) -> ItemType {get} } struct QueueType<T>: ExtraInformation { var items = [T]() mutating func insert(item: T) { items.append(item) mutating func delete() { items.remove(at: 0) //comformance to the ExtraInformation Protocol typealias ItemType = T var count: Int { return items.count subscript(i: Int) -> T { return items[i]
範例程式part2 var queueOfData = QueueType<Int>() queueOfData.insert(item: 100) queueOfData.insert(item: 200) queueOfData.insert(item: 300) queueOfData.insert(item: 400) queueOfData.insert(item: 500) print("陣列中有\(queueOfData.count)個元素") for i in queueOfData.items { print("\(i) ", terminator: "") } print("\n") queueOfData.delete() print("刪除100後,陣列中有\(queueOfData.count)個元素") queueOfData.insert(item: 600) print("加入600後,陣列中有\(queueOfData.count)個元素") print("queueOfData[2] = \(queueOfData[2])") print("")
輸出結果 陣列中有5個元素 100 200 300 400 500 刪除100後,陣列中有4個元素 200 300 400 500 加入600後,陣列中有5個元素 200 300 400 500 600 queueOfData[2] = 400