陣列 是 Swift 三種主要集合型別的其中之一。 陣列是一種有序的元素列表。 陣列可以儲存任何型別的元素,但同一個陣列中的所有元素都必須是相同的型別。 當陣列被指定給變數時,它是可變的,這表示你可以在建立陣列之後新增、移除或修改元素。 當陣列被指定給常數時,它就是不可變的,這表示它的內容無法被改變。
陣列字面值會寫成以逗號分隔的元素列表,並用方括號([...])包住。
Swift 可以從字面值中的元素推斷出陣列的型別。
let evenInts = [2, 4, 6, 8, 10, 12]
var oddInts = [1, 3, 5, 7, 9, 11, 13]
let greetings = ["Hello!", "Hi!", "¡Hola!"]
你也可以明確指定型別。
陣列型別有兩種寫法:Array<T>或簡寫語法[T],其中T是陣列所包含的值的型別。
let evenInts: Array<Int> = [2, 4, 6, 8, 10, 12]
var oddInts: [Int] = [1, 3, 5, 7, 9, 11, 13]
let greetings: [String] = ["Hello!", "Hi!", "¡Hola!"]
你可以使用陣列的count屬性來取得陣列中元素的數量:
evenInts.count
// returns 6
若要建立空陣列,就必須指定它的型別。 你可以使用陣列初始化語法,或明確的型別標註來達成:
let emptyArray = [Int]()
let emptyArray2 = Array<Int>()
let emptyArray3: [Int] = []
陣列可以巢狀化來建立多維陣列。
當你要明確指定巢狀陣列的型別時,請用巢狀的方括號把元素型別包起來,例如[[Int]]或Array<Array<Int>>:
let multiDimArray = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
let multiDimArray2: [[Int]] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
你可以使用append(_:)方法,把元素加到可變陣列的尾端:
var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.append(15)
// oddInts is now [1, 3, 5, 7, 9, 11, 13, 15]
你可以使用insert(_:at:)方法,在指定的索引插入元素。
這個方法接受兩個引數:要插入的元素,以及要插入的索引位置。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.insert(0, at: 0)
// oddInts is now [0, 1, 3, 5, 7, 9, 11, 13]
你可以使用+運算子把兩個陣列合併成單一陣列。
+運算子會建立並回傳一個新陣列;它不會修改原本的陣列。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
let combined = oddInts + [15, 17, 19]
// combined is [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
print(oddInts)
// prints [1, 3, 5, 7, 9, 11, 13]
你可以把索引放在陣列名稱後面的方括號([])裡,來存取陣列中的個別元素。
陣列的索引是以零為起始的Int值,第一個元素從0開始。
存取超出有效範圍的索引會造成執行期錯誤,並使程式崩潰。
let evenInts = [2, 4, 6, 8, 10, 12]
let oddInts = [1, 3, 5, 7, 9, 11, 13]
evenInts[2]
// returns 6
oddInts[7]
// Fatal error: Index out of range
你可以把新值指定給指定的索引,來改變可變陣列中的元素。 和讀取元素時一樣,使用超出有效範圍的索引會造成執行期錯誤。
var evenInts = [2, 4, 6, 8, 10, 12]
evenInts[2] = 0
// evenInts is now [2, 4, 0, 8, 10, 12]
你可以使用joined(separator:)方法,把字串陣列串接成單一字串,這個方法接受一個分隔字串:
let evenInts = ["2", "4", "6", "8", "10", "12"]
let evenIntsString = evenInts.joined(separator: ", ")
// returns "2, 4, 6, 8, 10, 12"
你可以使用split(separator:)方法,傳入分隔字元,把字串拆分成由子字串組成的陣列:
let evenIntsString = "2, 4, 6, 8, 10, 12"
let evenInts = evenIntsString.split(separator: ",")
// returns ["2", " 4", " 6", " 8", " 10", " 12"]
你可以使用remove(at:)方法,移除指定索引上的元素。
索引必須落在陣列的有效範圍內;否則會發生執行期錯誤。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.remove(at: 3)
// oddInts is now [1, 3, 5, 9, 11, 13]
若要移除陣列的最後一個元素,請使用removeLast()方法。
對空陣列呼叫removeLast()會造成執行期錯誤。
var oddInts = [1, 3, 5, 7, 9, 11, 13]
oddInts.removeLast()
// oddInts is now [1, 3, 5, 7, 9, 11]
準魔法師 Elyse 需要練習一些基本功。她有一疊牌,想要好好操作一番。
為了方便一些,她只用 1 到 10 的牌,這樣她的牌堆就能用數字陣列來表示。某張牌的位置對應到陣列中的索引,也就是說,位置 0 代表第一張牌,位置 1 代表第二張牌,以此類推。
所有函式都應該先更新牌的陣列,再回傳修改後的陣列。這是一種常見的做法,稱為 Builder 模式,可以讓你漂亮地把函式串接在一起。
要挑選一張牌,請從指定的牌堆回傳索引position處的牌。
實作函式getCard(at:from:),它接受兩個引數:at是牌在牌堆中的位置,from是牌堆。這個函式應該從指定的牌堆回傳位置index處的牌。
let index = 2
getCard(at: index, from: [1, 2, 4, 1])
// returns 4
施展一點手法,把索引position處的牌與提供的替換牌交換。
實作函式setCard(at:in:to),它接受三個引數:at是牌在牌堆中的位置,in是牌堆,to是要替換位置index處那張牌的新牌。這個函式應該回傳牌堆的副本,並將位置index處的牌替換成新牌。如果指定的index不是牌堆中的有效索引,就應該回傳原本的牌堆,保持不變。
let index = 2
let newCard = 6
setCard(at: index, in: [1, 2, 4, 1], to: newCard)
// returns [1, 2, 6, 1]
在牌堆頂端插入一張新牌,讓一張牌憑空出現。
實作函式insert(_:atTopOf:),它接受兩個引數:要插入的新牌,以及牌堆。這個函式應該回傳牌堆的副本,並將提供的新牌加到牌堆頂端。
let newCard = 8
insert(newCard, atTopOf: [5, 9, 7, 1])
// returns [5, 9, 7, 1, 8]
從牌堆移除指定position處的牌,讓一張牌消失。
實作函式removeCard(at:from:),它接受兩個引數:at是牌在牌堆中的位置,from是牌堆。這個函式應該回傳牌堆的副本,並移除位置index處的牌。如果指定的index不是牌堆中的有效索引,就應該回傳原本的牌堆,保持不變。
let index = 2
removeCard(at: index, from: [3, 2, 6, 4, 8])
// returns [3, 2, 4, 8]
在牌堆中指定的position處插入一張新牌,讓一張牌憑空出現。
實作函式insert(_:at:from:),它接受三個引數:要插入的新牌、新牌應該插入的位置,以及牌堆。這個函式應該回傳牌堆的副本,並將提供的新牌加到指定的位置。如果指定的index不是牌堆中的有效索引,就應該回傳原本的牌堆,保持不變。
let newCard = 8
insert(newCard, at: 2, from: [5, 9, 7, 1])
// returns [5, 9, 8, 7, 1]
檢查牌堆的大小是否等於stackSize。
實作函式checkSizeOfStack(_:_:),它接受兩個引數:stack是牌堆,stackSize是牌堆的大小。如果牌堆的大小等於stackSize,這個函式應該回傳true,否則回傳false。
let stackSize = 4
checkSizeOfStack([3, 2, 6, 4, 8], stackSize)
// returns false