集合的類型
Swift 語言提供Arrays
、Sets
和Dictionaries
三種基本的集合類型用來存儲集合數(shù)據(jù)。數(shù)組(Arrays
)是有序數(shù)據(jù)的集。集合(Sets
)是無序無重復(fù)數(shù)據(jù)的集。字典(Dictionaries
)是無序的鍵值對的集。
集合的可變性
如果創(chuàng)建一個Arrays
、Sets
或Dictionaries
并且把它分配成一個變量,這個集合將會是可變的。這意味著我們可以在創(chuàng)建之后添加更多或移除已存在的數(shù)據(jù)項(xiàng),或者改變集合中的數(shù)據(jù)項(xiàng)。如果我們把Arrays
、Sets
或Dictionaries
分配成常量,那么它就是不可變的,它的大小和內(nèi)容都不能被改變。
數(shù)組(Arrays)
數(shù)組使用有序列表存儲同一類型的多個值。相同的值可以多次出現(xiàn)在一個數(shù)組的不同位置中。
數(shù)組的簡單語法
寫 Swift 數(shù)組應(yīng)該遵循像Array<Element>
這樣的形式,其中Element
是這個數(shù)組中唯一允許存在的數(shù)據(jù)類型。我們也可以使用像[Element]
這樣的簡單語法。盡管兩種形式在功能上是一樣的,但是推薦較短的那種。
創(chuàng)建一個空數(shù)組
<pre><code>var someInts = [Int]() print("someInts is of type [Int] with \(someInts.count) items.") // 打印 "someInts is of type [Int] with 0 items." 注意,通過構(gòu)造函數(shù)的類型,someInts的值類型被推斷為[Int]。
</code></pre>
或者,如果代碼上下文中已經(jīng)提供了類型信息,例如一個函數(shù)參數(shù)或者一個 已經(jīng)定義好類型的常量或者變量,我們可以使用空數(shù)組語句創(chuàng)建一個空數(shù)組,它的寫法很簡單:[](一對空方括號):
<pre><code>someInts.append(3) // someInts 現(xiàn)在包含一個 Int 值 someInts = [] // someInts 現(xiàn)在是空數(shù)組,但是仍然是 [Int] 類型的。
</code></pre>
創(chuàng)建一個帶有默認(rèn)值的數(shù)組
Swift 中的Array
類型還提供一個可以創(chuàng)建特定大小并且所有數(shù)據(jù)都被默認(rèn)的構(gòu)造方法。我們可以把準(zhǔn)備加入新數(shù)組的數(shù)據(jù)項(xiàng)數(shù)量(count
)和適當(dāng)類型的初始值(repeatedValue
)傳入數(shù)組構(gòu)造函數(shù):
<pre><code>var threeDoubles = [Double](count: 3, repeatedValue:0.0) // threeDoubles 是一種 [Double] 數(shù)組,等價于 [0.0, 0.0, 0.0]
</code></pre>
通過兩個數(shù)組相加創(chuàng)建一個數(shù)組
我們可以使用加法操作符(+
)來組合兩種已存在的相同類型數(shù)組。新數(shù)組的數(shù)據(jù)類型會被從兩個數(shù)組的數(shù)據(jù)類型中推斷出來:
<pre><code>```var anotherThreeDoubles = Array(count: 3, repeatedValue: 2.5)
// anotherThreeDoubles 被推斷為 [Double],等價于 [2.5, 2.5, 2.5]
var sixDoubles = threeDoubles + anotherThreeDoubles
// sixDoubles 被推斷為 [Double],等價于 [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]```</code></pre>
用字面量構(gòu)造數(shù)組
我們可以使用字面量來進(jìn)行數(shù)組構(gòu)造,這是一種用一個或者多個數(shù)值構(gòu)造數(shù)組的簡單方法。字面量是一系列由逗號分割并由方括號包含的數(shù)值:
<pre><code>[value 1, value 2, value 3]。
</code></pre>
下面這個例子創(chuàng)建了一個叫做shoppingList
并且存儲String
的數(shù)組:
<pre><code>var shoppingList: [String] = ["Eggs", "Milk"] // shoppingList 已經(jīng)被構(gòu)造并且擁有兩個初始項(xiàng)。
</code></pre>
shoppingLis
t變量被聲明為“字符串值類型的數(shù)組“,記作[String]
。 因?yàn)檫@個數(shù)組被規(guī)定只有String
一種數(shù)據(jù)結(jié)構(gòu),所以只有String
類型可以在其中被存取。 在這里,shoppinglist
數(shù)組由兩個String
值("Eggs"
和"Milk"
)構(gòu)造,并且由字面量定義。
注意:
Shoppinglist
數(shù)組被聲明為變量(var
關(guān)鍵字創(chuàng)建)而不是常量(let
創(chuàng)建)是因?yàn)橐院罂赡軙懈嗟臄?shù)據(jù)項(xiàng)被插入其中。
在這個例子中,字面量僅僅包含兩個String
值。匹配了該數(shù)組的變量聲明(只能包含String
的數(shù)組),所以這個字面量的分配過程可以作為用兩個初始項(xiàng)來構(gòu)造shoppinglist
的一種方式。
由于 Swift 的類型推斷機(jī)制,當(dāng)我們用字面量構(gòu)造只擁有相同類型值數(shù)組的時候,我們不必把數(shù)組的類型定義清楚。shoppinglist
的構(gòu)造也可以這樣寫:
<pre><code>var shoppingList = ["Eggs", "Milk"]
</code></pre>
因?yàn)樗凶置媪恐械闹刀际窍嗤念愋停琒wift 可以推斷出[String]
是shoppinglist
中變量的正確類型。
訪問和修改數(shù)組
我們可以通過數(shù)組的方法和屬性來訪問和修改數(shù)組,或者使用下標(biāo)語法。
可以使用數(shù)組的只讀屬性count
來獲取數(shù)組中的數(shù)據(jù)項(xiàng)數(shù)量:
<pre><code>print("The shopping list contains \(shoppingList.count) items.") // 輸出 "The shopping list contains 2 items."(這個數(shù)組有2個項(xiàng))
</code></pre>
使用布爾值屬性isEmpty
作為檢查count
屬性的值是否為 0 的捷徑:
<pre><code>if shoppingList.isEmpty { print("The shopping list is empty.") } else { print("The shopping list is not empty.") } // 打印 "The shopping list is not empty."(shoppinglist 不是空的)
</code></pre>
也可以使用append(_:)
方法在數(shù)組后面添加新的數(shù)據(jù)項(xiàng):
<pre><code>shoppingList.append("Flour") // shoppingList 現(xiàn)在有3個數(shù)據(jù)項(xiàng),有人在攤煎餅
</code></pre>
除此之外,使用加法賦值運(yùn)算符(+=
)也可以直接在數(shù)組后面添加一個或多個擁有相同類型的數(shù)據(jù)項(xiàng):
<pre><code>shoppingList += ["Baking Powder"] // shoppingList 現(xiàn)在有四項(xiàng)了 shoppingList += ["Chocolate Spread", "Cheese", "Butter"] // shoppingList 現(xiàn)在有七項(xiàng)了
</code></pre>
可以直接使用下標(biāo)語法來獲取數(shù)組中的數(shù)據(jù)項(xiàng),把我們需要的數(shù)據(jù)項(xiàng)的索引值放在直接放在數(shù)組名稱的方括號中:
<pre><code>var firstItem = shoppingList[0] // 第一項(xiàng)是 "Eggs"
</code></pre>
注意:
第一項(xiàng)在數(shù)組中的索引值是0而不是1。 Swift 中的數(shù)組索引總是從零開始。
我們也可以用下標(biāo)來改變某個已有索引值對應(yīng)的數(shù)據(jù)值:
<pre><code>shoppingList[0] = "Six eggs" // 其中的第一項(xiàng)現(xiàn)在是 "Six eggs" 而不是 "Eggs"
</code></pre>
還可以利用下標(biāo)來一次改變一系列數(shù)據(jù)值,即使新數(shù)據(jù)和原有數(shù)據(jù)的數(shù)量是不一樣的。下面的例子把"Chocolate Spread"
,"Cheese"
,和"Butter"
替換為"Bananas"
和 "Apples"
:
<pre><code>shoppingList[4...6] = ["Bananas", "Apples"] // shoppingList 現(xiàn)在有6項(xiàng)
</code></pre>
注意:
不可以用下標(biāo)訪問的形式去在數(shù)組尾部添加新項(xiàng)。
調(diào)用數(shù)組的insert(_:atIndex:)
方法來在某個具體索引值之前添加數(shù)據(jù)項(xiàng):
<pre><code>shoppingList.insert("Maple Syrup", atIndex: 0) // shoppingList 現(xiàn)在有7項(xiàng) // "Maple Syrup" 現(xiàn)在是這個列表中的第一項(xiàng)
</code></pre>
這次insert(_:atIndex:)
方法調(diào)用把值為"Maple Syrup"
的新數(shù)據(jù)項(xiàng)插入列表的最開始位置,并且使用0作為索引值。
類似的我們可以使用removeAtIndex(_:)
方法來移除數(shù)組中的某一項(xiàng)。這個方法把數(shù)組在特定索引值中存儲的數(shù)據(jù)項(xiàng)移除并且返回這個被移除的數(shù)據(jù)項(xiàng)(我們不需要的時候就可以無視它):
<pre><code>let mapleSyrup = shoppingList.removeAtIndex(0) // 索引值為0的數(shù)據(jù)項(xiàng)被移除 // shoppingList 現(xiàn)在只有6項(xiàng),而且不包括 Maple Syrup // mapleSyrup 常量的值等于被移除數(shù)據(jù)項(xiàng)的值 "Maple Syrup"
</code></pre>
注意:
如果我們試著對索引越界的數(shù)據(jù)進(jìn)行檢索或者設(shè)置新值的操作,會引發(fā)一個運(yùn)行期錯誤。我們可以使用索引值和數(shù)組的count
屬性進(jìn)行比較來在使用某個索引之前先檢驗(yàn)是否有效。除了當(dāng)count
等于 0 時(說明這是個空數(shù)組),最大索引值一直是count
- 1,因?yàn)閿?shù)組都是零起索引。
數(shù)據(jù)項(xiàng)被移除后數(shù)組中的空出項(xiàng)會被自動填補(bǔ),所以現(xiàn)在索引值為0的數(shù)據(jù)項(xiàng)的值再次等于"Six eggs"
:
<pre><code>firstItem = shoppingList[0] // firstItem 現(xiàn)在等于 "Six eggs"
</code></pre>
如果我們只想把數(shù)組中的最后一項(xiàng)移除,可以使用removeLast()
方法而不是removeAtIndex(_:)
方法來避免我們需要獲取數(shù)組的count
屬性。就像后者一樣,前者也會返回被移除的數(shù)據(jù)項(xiàng):
<pre><code>let apples = shoppingList.removeLast() // 數(shù)組的最后一項(xiàng)被移除了 // shoppingList 現(xiàn)在只有5項(xiàng),不包括 cheese // apples 常量的值現(xiàn)在等于 "Apples" 字符串
</code></pre>
數(shù)組的遍歷
我們可以使用for-in
循環(huán)來遍歷所有數(shù)組中的數(shù)據(jù)項(xiàng):
<pre><code>for item in shoppingList { print(item) } // Six eggs // Milk // Flour // Baking Powder // Bananas
</code></pre>
如果我們同時需要每個數(shù)據(jù)項(xiàng)的值和索引值,可以使用enumerate()
方法來進(jìn)行數(shù)組遍歷。enumerate()
返回一個由每一個數(shù)據(jù)項(xiàng)索引值和數(shù)據(jù)值組成的元組。我們可以把這個元組分解成臨時常量或者變量來進(jìn)行遍歷:
<pre><code>for (index, value) in shoppingList.enumerate() { print("Item \(String(index + 1)): \(value)") } // Item 1: Six eggs // Item 2: Milk // Item 3: Flour // Item 4: Baking Powder // Item 5: Bananas
</code></pre>