學習軌道
/
Swift
Swift
/
練習
/
見習魔術師
見習魔術師

見習魔術師

學習練習

簡介

陣列 是 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 代表第二張牌,以此類推。

Note

所有函式都應該先更新牌的陣列,再回傳修改後的陣列。這是一種常見的做法,稱為 Builder 模式,可以讓你漂亮地把函式串接在一起。

1. 從牌堆取出一張牌

要挑選一張牌,請從指定的牌堆回傳索引position處的牌。

實作函式getCard(at:from:),它接受兩個引數:at是牌在牌堆中的位置,from是牌堆。這個函式應該從指定的牌堆回傳位置index處的牌。

let index = 2
getCard(at: index, from: [1, 2, 4, 1])
// returns 4

2. 更換牌堆中的一張牌

施展一點手法,把索引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]

3. 在牌堆頂端插入一張牌

在牌堆頂端插入一張新牌,讓一張牌憑空出現。

實作函式insert(_:atTopOf:),它接受兩個引數:要插入的新牌,以及牌堆。這個函式應該回傳牌堆的副本,並將提供的新牌加到牌堆頂端。

let newCard = 8
insert(newCard, atTopOf: [5, 9, 7, 1])
// returns [5, 9, 7, 1, 8]

4. 從牌堆移除一張牌

從牌堆移除指定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]

5. 在牌堆中插入一張牌

在牌堆中指定的position處插入一張新牌,讓一張牌憑空出現。

實作函式insert(_:at:from:),它接受三個引數:要插入的新牌、新牌應該插入的位置,以及牌堆。這個函式應該回傳牌堆的副本,並將提供的新牌加到指定的位置。如果指定的index不是牌堆中的有效索引,就應該回傳原本的牌堆,保持不變。

let newCard = 8
insert(newCard, at: 2, from: [5, 9, 7, 1])
// returns [5, 9, 8, 7, 1]

6. 檢查牌堆的大小

檢查牌堆的大小是否等於stackSize。

實作函式checkSizeOfStack(_:_:),它接受兩個引數:stack是牌堆,stackSize是牌堆的大小。如果牌堆的大小等於stackSize,這個函式應該回傳true,否則回傳false。

let stackSize = 4
checkSizeOfStack([3, 2, 6, 4, 8], stackSize)
// returns false
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Swift Exercism

準備好開始 見習魔術師 了嗎?

註冊 Exercism,透過 35 個概念116 個練習 和真人引導來學習並精通 Swift,全部免費。