Swift 5.1 (4) - 集合類型

集合類型

Swift提供三種主要的集合類型,稱為Array,SetDictionary,用于存儲(chǔ)值的集合。Array是有序的值的集合。Set是唯一值的無序集合。Dictionary是鍵值關(guān)聯(lián)的無序集合。
可變集合:
如果創(chuàng)建數(shù)組,集合或字典,并將其分配給變量,則創(chuàng)建的集合將是可變的。我們可以通過添加,刪除或更改集合中的項(xiàng)目來更改集合。如果將數(shù)組,集合或字典分配給常量,則該集合是不可變的,并且其大小和內(nèi)容不能更改。
數(shù)組:
數(shù)組可以存儲(chǔ)相同類型的值,并且相同的值可以在數(shù)組不同位置多次出現(xiàn)。

  1. 數(shù)組類型的簡(jiǎn)寫語法:a. Array <Element> b. [Element]其中Element是允許數(shù)組存儲(chǔ)的值的類型。其中[Element]簡(jiǎn)寫形式優(yōu)選。
  2. 創(chuàng)建一個(gè)空的數(shù)組:
    使用初始化語法創(chuàng)建某個(gè)類型的空數(shù)組:
//方式一
let intArray = Array<Int>()
print("intArray中有\(zhòng)(intArray.count)個(gè)元素")
//方式二
let intArray = [Int]()
print("intArray中有\(zhòng)(intArray.count)個(gè)元素")

如果上下文已經(jīng)提供了數(shù)組中的類型信息,則數(shù)組存儲(chǔ)的值得類型就是確定的。

  1. 創(chuàng)建帶有初始值得數(shù)組:
    Swift的Array類型提供了一個(gè)初始化方法,用于創(chuàng)建一個(gè)特定大小的數(shù)組,并將其所有值設(shè)置為相同的默認(rèn)值。
let defaultValueArray = Array.init(repeating: "你好", count: 3)
print(defaultValueArray)//!< ["你好", "你好", "你好"]
  1. 兩個(gè)數(shù)組相加:
    使用加法運(yùn)算符+將兩個(gè)具有兼容類型的現(xiàn)有數(shù)組相加來創(chuàng)建新數(shù)組。新數(shù)組的類型是從我們添加的兩個(gè)數(shù)組的類型推斷出來的。這兩個(gè)相加的數(shù)組的類型必須要可以兼容,否則編譯器會(huì)報(bào)錯(cuò)。
let defaultValueArray = Array.init(repeating: "你好", count: 3)
let secondValueArray = Array.init(repeating: "大佬", count: 2)
let thirdValueArray = defaultValueArray + secondValueArray
print(thirdValueArray)//!< ["你好", "你好", "你好", "大佬", "大佬"]
  1. 使用字面量元素初始化數(shù)組:
    使用數(shù)組字面量元素初始化數(shù)組,語法:[value 1, value 2, value 3]
let literalArray = ["逗哥","刀哥"] //!< ["逗哥", "刀哥"] 有初值,可以類型推斷,不必聲明數(shù)組的類型
let literalArray1 : [Int] = [6,7]//!< [6, 7] 聲明了類型
  1. 數(shù)組的訪問和修改:
    count屬性:訪問數(shù)組元素的個(gè)數(shù)。isEmpty屬性值Bool類型數(shù)組判空,相較Array.count == 0更高效。
if intArray.isEmpty {
   print("intArray:\(intArray)中有\(zhòng)(intArray.count)個(gè)元素")//!< intArray:[]中有0個(gè)元素
}

使用append(_:)方法拼接新項(xiàng)到數(shù)組的末尾

var appendArray = ["飛哥","強(qiáng)哥"]
appendArray.append("大哥")//!< ["飛哥", "強(qiáng)哥", "大哥"]

使用加法賦值運(yùn)算符+=追加一個(gè)或多個(gè)兼容項(xiàng)的數(shù)組:

var appendArray = ["飛哥","強(qiáng)哥"]
let array1 = ["finally","ok"]
let array2 = ["拯救","靜","\u{65}"]
appendArray += array1 //!< ["飛哥", "強(qiáng)哥", "finally", "ok"]
appendArray += array2 //!< ["飛哥", "強(qiáng)哥", "finally", "ok", "拯救", "靜", "e"]

使用下標(biāo)從數(shù)組中取值:

let literalArray = ["逗哥","刀哥"] //!< ["逗哥", "刀哥"]
let firstStr = literalArray[0]
print(firstStr) //!< 逗哥

使用下標(biāo)更改給定索引處的值:

var literalArray = ["逗哥","刀哥"] //!< ["逗哥", "刀哥"]
literalArray[0] = "加油"
print(literalArray) //!< ["加油", "刀哥"]

使用范圍下標(biāo)一次性更改值,即使替換值的數(shù)組長(zhǎng)度與要替換的范圍不同。但是必須不能越界:下標(biāo)范圍必須在當(dāng)前數(shù)組的有效范圍內(nèi)。

var totalArray = ["飛哥", "強(qiáng)哥", "finally", "ok", "拯救", "靜", "e"]
totalArray[...3] = ["","","","?"]//!< ["", "", "", "?", "拯救", "靜", "e"]
totalArray[5..<7] = ["融合了"]//!< 5..<7有兩個(gè)元素 被替換成了一個(gè) log:["", "", "", "?", "拯救", "融合了"]
print(totalArray)

使用insert(_:at :)方法在指定索引處將指定項(xiàng)插入數(shù)組:

var literalArray = ["逗哥","刀哥"] //!< ["逗哥", "刀哥"]
literalArray.insert("妄言", at: 1)//!< ["逗哥", "妄言", "刀哥"]
print(literalArray)

使用remove(at :)方法從數(shù)組中刪除指定項(xiàng)并返回刪除項(xiàng)

var literalArray = ["逗哥","刀哥"] //!< ["逗哥", "刀哥"]
literalArray.insert("妄言", at: 1)//!< ["逗哥", "妄言", "刀哥"]
let deleteStr = literalArray.remove(at: 0)//!< ["妄言", "刀哥"]
print(literalArray,"刪除了:\(deleteStr)")//!< ["妄言", "刀哥"] 刪除了:逗哥

使用removeLast()從數(shù)組中刪除最終項(xiàng)并返回刪除項(xiàng)。以避免需要查詢數(shù)組的count屬性.

var literalArray = ["逗哥","刀哥"] //!< ["逗哥", "刀哥"]
literalArray.removeLast()
//!< 也可以removeFirst()
literalArray.removeFirst()
  1. 數(shù)組的遍歷
    使用for-in循環(huán)遍歷
var literalArray = ["逗哥","刀哥"] //!< ["逗哥", "刀哥"]
for item in literalArray {
    print(item,"", separator: " ", terminator: "")//!< 逗哥 刀哥
}

使用enumerated()方法迭代數(shù)組:同時(shí)遍歷各項(xiàng)的整數(shù)索引及其值。
返回由整數(shù)和各項(xiàng)的值組成的元組。

for item in literalArray.enumerated() {
    print(item.1) //!< 逗哥 刀哥
    print(item.0) //!< 0 1
    print(item) //!< (offset: 0, element: "逗哥") (offset: 1, element: "刀哥")
}

集合:
Set是唯一值的無序集合,這個(gè)特性可以讓我們?cè)谶m當(dāng)?shù)膱?chǎng)景下去使用。

  1. 集合類型的值(散列,哈希)
    必須是可散列的類型才能存儲(chǔ)在集合中。 即:集合中存儲(chǔ)的類型必須提供能夠計(jì)算自身散列值的方法。哈希值是一個(gè)Int值,對(duì)于所有相互比較相等的對(duì)象都是相同的,例如a == b,則遵循a.hashValue == b.hashValue。
    默認(rèn)情況下,Swift的所有基本類型,如StringInt,DoubleBool都是可哈希的,并且可以用作集合中的值類型或字典的key類型。默認(rèn)情況下,沒有關(guān)聯(lián)值的枚舉類型也是可以哈希的。
    注意點(diǎn):我們可以使用自定義符合Hashable協(xié)議的類型作為集合中的值類型或字典的key類型。符合Hashable協(xié)議的類型必須提供名為hashValueInt類型的可訪問的屬性。該自定義類型的hashValue屬性在同一程序的不同執(zhí)行或不同程序中執(zhí)行時(shí)返回的值不需要相同。因?yàn)?code>Hashable協(xié)議繼承Equatable協(xié)議,所以符合Hashable協(xié)議的類型還必須提供運(yùn)算符==的實(shí)現(xiàn)。
    Equatable協(xié)議要求任何符合==實(shí)現(xiàn)的,都是相等關(guān)系。==的實(shí)現(xiàn)必須要滿足三個(gè)條件:反身性,對(duì)稱性,及物性。
    比如實(shí)現(xiàn)Equatable協(xié)議的類型的值a,b,c:
    ?反身性表示:a == a
    ?對(duì)稱性表示:a == b則b == a
    ?及物性表示:a == b && b == c則 a == c
  2. 集合類型語法:Set <Element>,其中Element是允許集合存儲(chǔ)的類型。與數(shù)組不同,集合沒有等效的簡(jiǎn)寫形式。
  3. 創(chuàng)建空集合:
let emptySet = Set<Int>()
let emptyCharacterSet = Set<Character>()

如果上下文已經(jīng)提供了集合中的類型信息,則集合中存儲(chǔ)的值得類型就是確定的。

  1. 使用數(shù)組創(chuàng)建集合
    使用數(shù)組初始化集合,將一個(gè)或多個(gè)值寫入集合中。
var favoriteGenres :Set<String> = ["可是","怎么","能夠","如此"]
//! 由于Swift的類型推斷的存在,在上下文提供了類型信息后,可以簡(jiǎn)寫為
var favoriteGenres :Set = ["可是","怎么","能夠","如此"]
  1. 集合的訪問和修改
    count屬性:訪問集合中元素的個(gè)數(shù)。isEmptyBool類型的屬性值用于集合判空。
if favoriteGenres.isEmpty {
    print("favoriteGenres集合中沒有元素")
    
} else {
    print("favoriteGenres集合有 \(favoriteGenres.count)個(gè)元素")
    
}

使用insert(_:)方法添加一個(gè)新項(xiàng)到集合中:

favoriteGenres.insert("聰明")//!< ["聰明", "能夠", "可是", "怎么", "如此"]

使用remove(_ :)方法從集合中刪除指定項(xiàng)并返回刪除項(xiàng):如果該項(xiàng)目是該集合的成員,則刪除該項(xiàng)目,并返回已刪除的值,如果該集合不包含該項(xiàng)目,則返回nil

if let removeItem = favoriteGenres.remove("聰明") {
    print("\(removeItem)此項(xiàng)已被移除")
} else {
    print("favoriteGenres集合中沒有該項(xiàng)")
}

使用contains(_:)方法,判斷集合中是否包含某一項(xiàng)。

if favoriteGenres.contains("好的") {
    print("包含")
} else {
    print("不包含")
}
  1. 集合的遍歷
    使用for-in循環(huán)遍歷
var favoriteGenres :Set = ["可是","怎么","能夠","如此"]
for item in favoriteGenres {
    print(item,"",separator: " ", terminator: "")//!< 能夠 怎么 如此 可是
}

使用sorted()方法,以特定順序遍歷集合的值,該方法將集合的元素使用<運(yùn)算符排序后的元素作為數(shù)組返回。

for item in favoriteGenres.sorted() {
    print(item)
}
  1. 集合的操作
    兩組集合a和b以陰影區(qū)域表示的各種集合操作的結(jié)果。


    集合操作圖示
  • 使用intersection(_ :)方法創(chuàng)建一個(gè)只包含兩個(gè)集合共有的值的新集合。
  • 使用symmetricDifference(_ :)方法創(chuàng)建一個(gè)新集合,其中包含任一集合中的值,但不包含兩個(gè)集合共同的部分。
  • 使用union(_ :)方法創(chuàng)建一個(gè)包含兩個(gè)集合中所有值的新集合。
  • 使用subtracting(_:)方法創(chuàng)建一個(gè)值不在指定集中的新集。
let set1 : Set<Int> = Set.init(arrayLiteral: 1,5,7,2)
let set2 : Set<Int> = [2,4,6,8]
let set3 = set1.intersection(set2)//!< 預(yù)期:[2] 實(shí)際 [2]
//除了相同以外的其他元素
let set4 = set1.symmetricDifference(set2)//!< 預(yù)期:[1,5,7,4,6,8] 實(shí)際: [6, 4, 5, 7, 8, 1]
let set5 = set1.union(set2)//!< 預(yù)期[6, 4, 5, 7, 8, 1,2] 實(shí)際 [4, 5, 2, 8, 1, 7, 6]
//從set1中去除與set2有關(guān)的所有元素
let set6 = set1.subtracting(set2)//!< 預(yù)期[1,5,7] 實(shí)際[1, 7, 5]
  1. 集合之間的關(guān)系與相等判斷:三個(gè)集合a,b和c,集合a包含集合b中的所有元素,則稱集合a是集合b的超集,相反,集合b是集合a的子集。集合b和集合c沒有共同的元素。集合a和集合c有共同的元素,則集合a和集合c相交。
    ?使用運(yùn)算符==確定兩個(gè)集合是否包含所有相同的值。
    ?使用isSubset(of :)方法確定集合的所有值是否包含在指定集合中。
    ?使用isSuperset(of :)方法確定集合是否包含指定集合中的所有值。
    ?使用isStrictSubset(of :)或isStrictSuperset(of :)方法來確定集合是否是指定集合的??子集或超集,但不能判斷相等。
    ?使用isDisjoint(with :)方法確定兩個(gè)集合是否沒有有共同的值。
let set : Set<Int> = [1,5,2,7]
let set1 : Set<Int> = Set.init(arrayLiteral: 1,5,7,2,8)
//! 判斷相等
if set == set1 {
    print("相等")
} else {
    print("不相等")
}
//!判斷子集與超集
if set.isStrictSubset(of: set1){//!< set是否是set1的子集
    print("set是set1的子集")
}
if set1.isStrictSubset(of: set){//!< set1是否是set的超集
    print("set1是set的超集")
}
//!< 判斷是否不相交
if set1.isDisjoint(with: set) {//!< `true`元素不相交 否則`false`
    print("set1和set不相交")
} else {
    print("set1和set相交")
}

字典:

  1. 字典類型的簡(jiǎn)寫語法:
    a.Dictionary <Key,Value>。b. [Key:Value]。其中Key表示字典中鍵的值的類型,Value表示存儲(chǔ)的值的類型。
    字典Key類型必須符合Hashable協(xié)議,就像集合的值類型一樣。
  2. 創(chuàng)建一個(gè)空的字典:
//方式一
let namesOfIntegers :Dictionary<Int,String> = Dictionary<Int,String>.init()
let namesOfIntegers  = Dictionary<Int,String>.init()
let namesOfIntegers  = Dictionary<Int,String>()

//方式二
let namesOfIntegers  = [Int:String].init() //!< [:]
let namesOfIntegers = [Int:String]()
//方式三:提供類型信息
let namesOfIntegers : [Int:String] = [:]

如果上下文已經(jīng)提供了字典中的類型信息,則字典中的類型信息就是確定的。

  1. 創(chuàng)建帶初始值的字典:
let airports : [String:String] = [String:String].init(dictionaryLiteral: ("name","zhangfei"),("age","16"),("職業(yè)","將軍"))//!< ["職業(yè)": "將軍", "age": "16", "name": "zhangfei"]

簡(jiǎn)寫語法:[key 1: value 1, key 2: value 2, key 3: value 3]

//鍵值類型都相同,swift樂行推斷,故省略字典類型
let airports = ["職業(yè)": "將軍", "age": "16", "name": "zhangfei"]
//以下類型的字典就不能類型推斷,必須聲明字典的鍵值類型
 let airports : [String : Any] = ["職業(yè)": "將軍", "age": 16, "name": "zhangfei"]
  1. 字典的訪問和修改
    count屬性:訪問字典鍵值對(duì)的個(gè)數(shù)。isEmpty屬性值Bool類型,字典判空
if airports.isEmpty {
    print("airports是空的")
} else {
    print("airports:\(airports)中有\(zhòng)(airports.count)個(gè)元素")//!< airports:["name": "zhangfei", "職業(yè)": "將軍", "age": "16"]中有3個(gè)元素
}

添加新項(xiàng)到字典中

//方式一.使用下標(biāo)語法
var airports = ["job": "將軍", "age": "16", "name": "zhangfei"]
airports["sex"] = "男"
//方式二
var airports = ["job": "將軍", "age": "16", "name": "zhangfei"]
airports.updateValue("男", forKey: "sex")
print(airports)//!< ["sex": "男", "job": "將軍", "age": "16", "name": "zhangfei"]

更改與特定鍵關(guān)聯(lián)的值

//方式一.使用下標(biāo)語法
var airports = ["job": "將軍", "age": "16", "name": "zhangfei"]
airports["job"] = "主公"
//方式二
var airports = ["job": "將軍", "age": "16", "name": "zhangfei"]
airports.updateValue("主公", forKey: "job")
print(airports)//!< ["age": "16", "job": "主公", "name": "zhangfei"]

上述示例中updateValue(_:forKey:)方法,若是key在字典中已存在,則更改其對(duì)應(yīng)的值為新值,并且返回其對(duì)應(yīng)的舊值。若key在字典中不存在,則返回nil,并且添加這個(gè)新的鍵值對(duì)到字典中,因?yàn)榉祷刂悼?code>nil故此方法的返回值是可選類型。

if let oldValue =  airports.updateValue("男", forKey: "sex") {
    print("key早就已經(jīng)存在了,并且舊值為\(oldValue)")
} else {
    print("key不存在,需添加到字典中")//!< log:key不存在,需添加到字典中
}

刪除字典中鍵值對(duì):

//方式一.使用下標(biāo)語法
var airports = ["job": "將軍", "age": "16", "name": "zhangfei"]
airports["job"] = nil
//方式二
if let value = airports.removeValue(forKey: "job") {
     print("The value \(value) was removed.")//!< The value 將軍 was removed.
}
print(airports)//!< ["age": "16", "name": "zhangfei"]

上述示例中removeValue(_:forKey:)方法,若是key在字典中已存在,則移除,并且返回該移除項(xiàng)的值。若key在字典中不存在,則返回nil,(不存在鍵值對(duì),無法做移除)因?yàn)榉祷刂悼蒼il故此方法的返回值是可選類型。

  1. 字典的遍歷:
    使用for-in循環(huán)遍歷字典中的鍵值對(duì)。字典中的每項(xiàng)都會(huì)作為(key, value)這樣的元組類型返回,并且我們可以再迭代的過程中將元組的成員分解為臨時(shí)常量或變量。
//! 方式一
for item in airports {
print("\(item.key)")
print("\(item.value)")
}
//! 方式二
for (key,value) in airports {
print("\(key)")
print("\(value)")
}

單獨(dú)遍歷其鍵或值

for key in airports.keys {
    print(key)
}
for value in airports.values {
    print(value)
}

keysvalues的類型轉(zhuǎn)換為數(shù)組。不可強(qiáng)轉(zhuǎn),類型不一致,需要重新初始化為Array類型

let keysArray = [String](airports.keys)
let valuesArray = Array<String>.init(airports.values)

Swift的Dictionary類型是無序的。要按特定順序遍歷字典的鍵或值,需要在字典的 keysvalues 屬性的基礎(chǔ)上使用sorted()方法(升序),得到有序的keys或values。

參考資料:
swift 5.1官方編程指南

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 級(jí)別: ★☆☆☆☆標(biāo)簽:「iOS」「Swift 5.1」「Set」「Array」「Dictionary」作者: 沐...
    QiShare閱讀 1,312評(píng)論 0 5
  • 案例代碼下載 集合類型 Swift提供三種主要的集合類型,為數(shù)組,集合和字典,用于存儲(chǔ)集合值。數(shù)組是有序的值集合。...
    酒茶白開水閱讀 469評(píng)論 0 0
  • Swift 語言提供Arrays、Sets和Dictionaries三種基本的集合類型用來存儲(chǔ)集合數(shù)據(jù)。數(shù)組(Ar...
    窮人家的孩紙閱讀 650評(píng)論 3 2
  • [The Swift Programming Language 中文版]本頁包含內(nèi)容: Swift 語言提供Arr...
    風(fēng)林山火閱讀 523評(píng)論 0 1
  • 我想養(yǎng)一只小動(dòng)物,不拘于貓或狗,鸚鵡也可。 依不依賴我都行,但我若是需要一個(gè)擁抱或者一起靜靜呆著,千萬別躲開。 喵...
    murill閱讀 168評(píng)論 0 2

友情鏈接更多精彩內(nèi)容