//swift 提供三種集合類型 來存儲集合數(shù)據(jù)
/*
Array Sets Dictionaries
數(shù)組 array 時有序數(shù)據(jù)的集,
集合Sets 是無序無重復數(shù)據(jù)的集
字典 dictionary 是無序的鍵值對的集
在存儲數(shù)據(jù)時,對數(shù)據(jù)值得類型明確,不能把不正確的值插入其中,我們對取回的值的類型完全自信
如果將集合用變量分配,那集合就會是可變的,我們就可以添加和刪除
如果是常量,那就是不可編輯的集合,內容,大小都不能改變
*/
/*
數(shù)組Arrays 數(shù)組使用有序列表存儲同一類型的多個值,相同的值可以多次出現(xiàn)在一個數(shù)組的不同位置
Swift中 Array 類型被橋接到 Foundation 中的 NSArray類,
Swift 應該遵循 Array<Element>其中 Element 是這個數(shù)組中唯一允許存在的數(shù)據(jù)類型 。
也可以使用語法糖,[Element] 這樣的簡單語法,推薦語法糖來寫
*/
//創(chuàng)建一個空數(shù)組
var someInts = [Int]()
print("someInts has \(someInts.count) items")
//someInts 被推斷值為Int類型的集合
someInts.append(3)
//此時數(shù)組中增加了一個元素 好比oc 的 addobject
print(someInts)
someInts = []//設置數(shù)組為空 但someints 仍是Int類型的集合
print(someInts)
//swift 還提供一個可以創(chuàng)建特定大小并且所有數(shù)據(jù)都被默認的構造方法,我們可以吧準備加入新數(shù)組的數(shù)據(jù)項數(shù)量(count),和適當類型的初始值(repeating)傳入數(shù)組構造函數(shù)
var threedoubles = Array(repeating: 0.0, count: 3)
print(threedoubles)
//通過兩個數(shù)組相加創(chuàng)建一個數(shù)組
var testarr = [Any]()//不能寫成 []()或 [] 在oc中可以 不確定類型用Any
// var newarr = threedoubles + testarr 報錯 說testarr 不確定類型的數(shù)組
var doublearr = [1.1,1.2,1.3]
var newarr = threedoubles + doublearr
print(newarr)//打印輸出結果 [0.0, 0.0, 0.0, 1.1000000000000001, 1.2, 1.3] 為什么會有1.100001?
// Decimal
var test1 = [Decimal](repeating: 0.1, count: 3)
var test = [Decimal]()
test = [1.1,1.2,1.3]
print(test)
//也可以這么寫 stringarr 被聲明為字符串值類型的數(shù)組,記為[string] 因此這個數(shù)組被規(guī)定只有string 一種數(shù)據(jù)類型結構,所以只有string 類型可以在其中被存取,在這里,stringarr由兩個數(shù)組字面量定義
var stringarr : [String] = ["hello","world"]
//由于swift 的類型推斷機制,當我們用字面量構造只擁有相同類型值數(shù)的時候,我們不必把數(shù)組的類型定義清除。
//只要初始的數(shù)組內所有的元素都是同一類型,那就該數(shù)組就會被推斷為同一的類型數(shù)組
//訪問數(shù)組 修改數(shù)組
// .count 訪問數(shù)組個數(shù) 與oc一樣
//用isEmpty 來判斷是否為空數(shù)組
if stringarr.isEmpty{
print("空數(shù)組")
}else{
print("非空數(shù)組")
}
//與string 一樣 用append 來追加和添加新數(shù)據(jù)項
stringarr.append("hello")
stringarr.append(contentsOf: ["666","777"]) //果然猜的沒錯 就是這么添加另一個數(shù)組
// stringarr.append(contentsOf: [1.1,2.2]) 報錯 數(shù)據(jù)類型不對
print(stringarr)
//另一種追加語法糖
stringarr += ["追加"]
print(stringarr)
// stringarr -= ["追加"] 報錯 -= 不能用在兩個數(shù)組中
// print(stringarr)
//追加 不能用下標訪問的形式去愛在數(shù)組尾部追加新項
//獲取數(shù)組某一數(shù)據(jù)項 與oc 一樣用下標方式
var firstone = stringarr[0] //獲取第一個數(shù)據(jù)項
print(firstone)
for 字符串 in stringarr{
print(字符串,terminator:"-")
}
//取一個范圍內的數(shù)據(jù)項
var arr = stringarr[2...4]
print(arr)
//插入數(shù)據(jù)項 用insert(_: at:)在某個具體的索引之前添加數(shù)據(jù)項
stringarr.insert("end", at: stringarr.count)//在個數(shù)之后追加 沒問題
print(stringarr)
// stringarr.count == stringarr.endIndex 刪除不能用count 和 endindex 下標
stringarr.remove(at: stringarr.endIndex-1)//在個數(shù)之后刪除 會越界,下標為個數(shù)的地方?jīng)]有值 超出了下標最大值
print(stringarr)
//在操作數(shù)組時,應該確保數(shù)組的有效性 數(shù)據(jù)項被移除后數(shù)組的空出項會被自動填補
//如果移除數(shù)組的最后一項 不應該用 remoe at 應該用removeLast()
stringarr.removeLast()//移除最后一個
stringarr.removeFirst()//移除第一個
//數(shù)組的遍歷 使用for in 來遍歷數(shù)據(jù)項
//如果我們同時需要每個數(shù)據(jù)項的值和索引值 可以使用enumerated()方法來進行數(shù)組遍歷.
//enumerated() 返回一個每一個數(shù)據(jù)項索引值和數(shù)據(jù)值組成的元組。就是返回索引和元素
//注意是元組 所以 for 后加 () 括號里面是 下標和值
//在oc中用過這種方法,但不知道會返回索引 只認為是遍歷數(shù)組的一種方式
for(index,value) in stringarr.enumerated(){
print(index,value)
}
//集合 Sets
//用來存儲相同類型并且沒有確定順序的值,當集合元素順序不重要時,或希望確保每個元素只出現(xiàn)一次時可以使用集合而不是數(shù)組
//Swift的Set類型被橋接到Foundation 中的NSSet類
/*集合類型的哈希值
一個類型為了存儲在集合中,該類型必須是可哈?;?-也就是說,該類型必須提供一個方法來計算它的哈希值。一個哈希值是Int類型的,相等的對象哈希值必須相同,比如a==b 那么 a.hashvalue== b.hashvalue
Swift的所有基本類型(比如String,Int,double,bool)默認都是哈希化的,可以作為集合的值得類型或者字典的鍵的類型。沒有關聯(lián)值得枚舉成員值(在枚舉有講述)默認也是可哈?;?*/
/*
你可以使用你自定義的類型作為集合的值得類型 或者是字典的鍵的類型,但你需要使你的自定義的類型符合Swift標準庫中的hashable協(xié)議。符合hashable協(xié)議的類型需要提供一個類型為Int的可讀屬性hashvalue。由類型的hashvalue屬性返回的值不需要在同一程序的不同執(zhí)行周期或者不同程序之間保持相同。
*/
/*
因為hashable協(xié)議符合Equatable協(xié)議。所以遵循該協(xié)議的類型也必須提供一個“是否相等”運算符==的實現(xiàn),這個Equatable協(xié)議要求任何符合 == 實現(xiàn)的實例間都是一種相等的關系。也就是說,對于abc三個值來說 == 的實現(xiàn)必須滿足下面三種情況
*/
/*
a == a 自反性
a == b 意味著 b == a 對稱性
a == b && b == c 意味著 a == c
*/
/*
集合類型語法
Swift 中的Set類型被寫為Set<element> 這里的element 表示Set中允許存儲的類型,和數(shù)組不同的是,集合沒有等價的簡化形式。md 就是沒有語法糖唄,還沒有等價的簡化形式,不仔細想想都tm看不懂說的啥。
*/
var letters = Set<Character>()//空的集合
// var settest : Set = [Character]() 報錯說不能轉化為值類型在 Set上 說明語法糖不能用
print("letters is of type Set<character> with \(letters.count)")
//根據(jù)上下文提供了類型信息,比如作為函數(shù)的參數(shù)或者已知類型的變量或常量,我們可以通過一個空的數(shù)組字面量創(chuàng)建一個空的set
letters.insert("a")
print(letters)
let has = 1
// letters.insert(has.hashValue) 試試行不行 因為已經(jīng)定義為character類型的集合了
letters = [] //這樣才可以用語法糖置空,因為已經(jīng)明確了類型
print(letters)
//用數(shù)組字面量創(chuàng)建集合
//可以使用數(shù)組字面量來構造集合,并且可以使用簡化形式寫一個或者多個值多為集合元素
//構造一個含有初始值的集合
var stringSet : Set<String> = ["hello","world","!"]
//一個set類型不能從數(shù)組字面量中被單獨推斷出來,因此set類型必須為顯示聲明,然而,由于Swift的類型推斷功能,如果你想使用一個數(shù)組字面量構造一個set并且該數(shù)組字面量中的所有元素類型相同,那么就可以不用寫出set的具體類型
var notype : Set = ["a","b","c"]//不能使用語法糖是錯的 要加上指定的類型 set 后面才可以用語法糖
notype.isEmpty //是否為空
notype.count //個數(shù)
notype.insert("insert") //插入一個元素 不是數(shù)組 沒有需要下標
print(notype)
notype.removeFirst()//刪除第一個
print(notype)
// notype.removeAll()//刪除所有
notype.removeAll(keepingCapacity: true)//有啥用? 我以為是刪除后,保留刪除前的所有元素開辟的空間,只是值不在了。更具arrayviewcapacity來看也是自動釋放的意思
print(notype,notype.count)
var notype1 : Set = ["a","b","c"]
//通過刪除一個元素,如果該值時set的一個元素則刪除該元素,并且返回被刪除的元素。如果set不包含則返回nil
if let removed = notype1.remove("a"){
print(removed,"移除a")
}else{
print("沒有匹配任何值")
}
if notype1.contains("b"){
print("包含元素")
}else{
print("不包含")
}
for item in notype1{
print("\(item)")
}
let newSet : Set = ["1","2","3","4"]
let oldSet : Set = ["3","4","5","6"]
//取相同
let same = newSet.intersection(oldSet)
print(same)
//取除相同之外
let nosame = newSet.symmetricDifference(oldSet)
print(nosame)
//去重復
let quchong = newSet.union(oldSet)
print(quchong)
//取出除另一個所有
let noOther = newSet.subtracting(oldSet)
print(noOther)
//取出后的新集合是無序的
//只需在括號后 加 .sorted() 進行排序
let union = newSet.union(oldSet).sorted()
print(union)
//判斷一個集合的值是否也在另一個集合中包含
//事實上 a只有部分被b包含 所以不行
if newSet.isSubset(of: oldSet){
print("a在b包含")
}else{
print("a不被b包含")
}
let a : Set = ["1","1"]
let b : Set = ["1","1","2","2"]//包含a
// let b : Set = ["1","2","2"]//包含a
if a.isSubset(of: b){
print("a在b包含")
}else{
print("a不被b包含")
}
//翻譯的不明確,應為一個集合中的所有元素 都在另一個集合中出現(xiàn)過,可以用 isSubset(of:)
//一個集合是否完全包含另一個b
if a.isSuperset(of: b){
print("a完全包含b")
}else{
print("a不完全包含b")
}
let c : Set = ["2","3","4"]
//使用 isStrictSubset(of:) isStrictSuperset(of:) 來判斷一個集合是否是另一個集合的自己和或父集合 并且兩個集合不相等
let q : Set = ["1","2"]
let w : Set = ["1","2"]
print(q.isSubset(of: w))//q是否被w包含 true
print(q.isSuperset(of: w))//q 是否包含w true
print(q.isStrictSubset(of: w))//q是否是w 的子集合 false
print(q.isStrictSuperset(of: w))//q是否是w的父集合 false
let x : Set = ["1","2"]
let y : Set = ["1","2","3"]
print(x.isSubset(of: y))//q是否被w包含 true
print(x.isSuperset(of: y))//q 是否包含w false
print(x.isStrictSubset(of: y))//q是否是w 的子集合 true
print(x.isStrictSuperset(of: y))//q是否是w的父集合 false
//使用isDisjoint(with:) 來判斷兩個集合是否不包含有相同的值(是否沒有交集)
//字典 Swift的Dictionary 類型被橋接到Oc 的 NSDictionary類
//一個字典的key 必須遵循h(huán)ashable協(xié)議 就想Set的值類型
//定義時,可以用dictionary<key,Value> 或者 語法糖 [key:value]
//創(chuàng)建一個空字典
var dict = [Int : String]()
dict = [1:"1",2:"2"]
print(dict)
//其中 4 是key 非下標
dict[4] = "2" //沒有使用增加方法 ,直接指定一個key設置上值 就新增了一個鍵值對
print(dict)
//在定義的時候不能用[:] 置為空的時候可以使用
dict = [:]
print(dict)
var airport : [String : String] = ["where":"beijing","money":"1000"]
//如果在構造字典時 如果每個值 或者 每個鍵 都是同一類型 就不需要定義類型
//使用isEmpty 來檢查count 是否為0
//使用count 來獲取字典的數(shù)據(jù)項個數(shù)
airport["haha"] = "xixi" //指定某個鍵為某個值
print(airport)
airport["where"] = "上海" //通過key來修改該key所對應的值
//作為另一種下標方法,字典的updatevalue(_:forkey:) 方法可以設置或者更新特定鍵對應的值。就想上面所示的下標示例,updatevalue(_:forkey:)方法在這個鍵不存在對應值得時候會設置新值或者在存在時更新已存在的值,和上面的下標方法不同的,updatevalue(_:forkey:)這個方法返回更新值之前的原值,這樣使得我們可以檢查更新是否成功
//updatevalue 方法會返回對應值得類型的可選值 對于存儲string 值得字典,這個函數(shù)會返回一個string? 或者 可選string類型的值
//如果有值存在于更新前,則這個可選值包含了舊值,否則它將會是nil
if let oldvalue = airport.updateValue("haha", forKey: "haha"){
print("oldvalue is \(oldvalue)") //執(zhí)行 有 haha key 返回haha 之前的值
}else{
print("nil")
}
print(airport["lala"])//訪問該key對應 的值,若key對應的值不存在 返回nil
if let newvalue = airport.updateValue("haha", forKey: "lala"){
print("oldvalue is \(newvalue)")
}else{
print("nil") //執(zhí)行 因為沒有l(wèi)ala 這個key
}
//removevalue(forkey:)方法也可以用來在字典中移除鍵值對,這個方法在鍵值對存在的情況下會移除該鍵值對并且返回被移除的值或者在沒有值的情況下返回nil
if let value = airport.removeValue(forKey: "money"){
print(value) //執(zhí)行 有money key 返回money key之前的值
}else{
print("no key money")
}
print(airport)
//字典遍歷
var json = ["1":"one","2":"two","3":"three","4":"four","5":"five"]
for (jsonkey,jsonvalue) in json{
print("\(jsonkey),\(jsonvalue)")
}
for key in json.keys{
print(key)
}
for value in json.values{
print(value)
}
//swift 的字典類型是無序的的集合類型 。為了以特定的順序遍歷字典的鍵或值,可以對字典的keys或者values屬性使用Sorted()方法
for sortedkey in json.keys.sorted(){
print(sortedkey)
}
for sortedvalue in json.values.sorted(){
print(sortedvalue)
}
var jsonChinese = ["安徽":"one","重慶":"two","安陽":"three","蚌埠":"four","支付寶":"five"]
for sortedkey in jsonChinese.keys{
print(sortedkey)
}
for sortedvalue in jsonChinese.keys.sorted(){
print(sortedvalue)
}
//然而對中文并沒有什么亂用 白高興一場 如果key是英文的話 會按英文的字母順序來排
輸出為
someInts has 0 items
[3]
[]
[0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 1.1000000000000001, 1.2, 1.3]
[1.1, 1.2, 1.3]
非空數(shù)組
["hello", "world", "hello", "666", "777"]
["hello", "world", "hello", "666", "777", "追加"]
hello
hello-world-hello-666-777-追加-["hello", "666", "777"]
["hello", "world", "hello", "666", "777", "追加", "end"]
["hello", "world", "hello", "666", "777", "追加"]
0 world
1 hello
2 666
3 777
letters is of type Set<character> with 0
["a"]
[]
["b", "insert", "a", "c"]
["insert", "a", "c"]
[] 0
a 移除a
包含元素
b
c
["3", "4"]
["2", "1", "6", "5"]
["4", "2", "1", "5", "6", "3"]
["2", "1"]
["1", "2", "3", "4", "5", "6"]
a不被b包含
a在b包含
a不完全包含b
true
true
false
false
true
false
true
false
[2: "2", 1: "1"]
[2: "2", 4: "2", 1: "1"]
[:]
["money": "1000", "haha": "xixi", "where": "beijing"]
oldvalue is xixi
nil
nil
1000
["haha": "haha", "where": "上海", "lala": "haha"]
4,four
2,two
1,one
5,five
3,three
4
2
1
5
3
four
two
one
five
three
1
2
3
4
5
five
four
one
three
two
安陽
支付寶
蚌埠
安徽
重慶
安徽
安陽
支付寶
蚌埠
重慶