Swift知识点4 - 集合类型

http://wiki.jikexueyuan.com/project/swift/
http://www.swift51.com/swift4.0/

集合类型

数组是有序的值的集合。合集是唯一值的无序集合。字典是无序的键值对集合。

Swift 的数组、合集和字典是以泛型集合实现的。

数组

Swift 数组的类型完整写法是 Array<Element>, Element是数组允许存入的值的类型。你同样可以简写数组的类型为 [Element]。

var someInts = [Int]()
var threeDoubles = Array(repeating: 0.0, count: 3)
var shoppingList = ["Eggs", "Milk"]

使用下标脚本语法来改变给定索引中已经存在的值:

shoppingList[0] = "Six eggs"
shoppingList[4...6] = ["Bananas", "Apples"]

遍历一个数组

for item in shoppingList {
    print(item)
}

如果你需要每个元素以及值的整数索引,使用 enumerated()方法来遍历数组。 enumerated()方法返回数组中每一个元素的元组,包含了这个元素的索引和值。你可以分解元组为临时的常量或者变量作为遍历的一部分:

for (index, value) in shoppingList.enumerated() {
    print("Item \(index + 1): \(value)")
}

Set 类型的哈希值

为了能让类型储存在合集当中,它必须是可哈希的——就是说类型必须提供计算它自身哈希值的方法。哈希值是Int值且所有的对比起来相等的对象都相同,比如 a == b,它遵循 a.hashValue == b.hashValue。

所有 Swift 的基础类型(比如 String, Int, Double, 和 Bool)默认都是可哈希的,并且可以用于合集或者字典的键。没有关联值的枚举成员值(如同[枚举]当中描述的那样)同样默认可哈希。

你可以使用你自己自定义的类型作为合集的值类型或者字典的键类型,只要让它们遵循 Swift 基础库的 Hashable协议即可。遵循 Hashable协议的类型必须提供可获取的叫做 hashValue的 Int属性。通过 hashValue属性返回的值不需要在同一个程序的不同的执行当中都相同,或者不同程序。

因为 Hashable协议遵循 Equatable,遵循的类型必须同时一个“等于”运算符 ( ==)的实现。 Equatable协议需要任何遵循 ==的实现都具有等价关系。就是说, ==的实现必须满足以下三个条件,其中 a, b, 和 c是任意值:

a == a (自反性)
a == b 意味着 b == a (对称性)
a == b && b == c 意味着 a == c (传递性)

自定义类型存入集合

// 自定义对象
class Person {
    var name: String?
    init(name: String) {
        self.name = name
    }
}

// 放入集合需要遵循hashable协议,实现协议相应方法
extension Person: Hashable {
    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.name == rhs.name
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(name)
    }
}

// 创建集合,此时是无序的集合
let nameSet: Set<Person> = [Person(name: "yuan"), Person(name: "zhi"), Person(name: "ying")]
for person in nameSet {
    print("排序前:\(person.name ?? "")")
}
//排序前:zhi
//排序前:ying
//排序前:yuan

// 集合排序
let sortedNameSet = nameSet.sorted(by: { (person1, person2) -> Bool in
    return (person1.name ?? "") < (person2.name ?? "")
})
for person in sortedNameSet {
    print("排序后:\(person.name ?? "")")
}
//排序后:ying
//排序后:yuan
//排序后:zhi

Swift 的合集类型写做 Set<Element>,这里的 Element是合集要储存的类型。不同与数组,合集没有等价的简写。

var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")

另外,如果内容已经提供了类型信息,比如函数的实际参数或者已经分类的变量常量,你就可以用空的数组字面量来创建一个空合集:

letters.insert("a")
// letters now contains 1 value of type Character
letters = []
// letters is now an empty set, but is still of type Set<Character>
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]

for-in循环里遍历合集的值

for genre in favoriteGenres {
    print("\(genre)")
}

Swift 的 Set类型是无序的。要以特定的顺序遍历合集的值,使用 sorted()方法,它把合集的元素作为使用 < 运算符排序了的数组返回。

for genre in favoriteGenres.sorted() {
    print("\(genre)")
}

数组转集合

let array1 = [1, 2, 3, 4, 5, 5, 6, 4]
let set1 = Set.init(array1)
for set in set1 {
    print(set)
}
WX20180301-171651@2x.png

使用 intersection(:)方法来创建一个只包含两个合集共有值的新合集;
使用 symmetricDifference(
:)方法来创建一个只包含两个合集各自有的非共有值的新合集;
使用 union(:)方法来创建一个包含两个合集所有值的新合集;
使用 subtracting(
:)方法来创建一个两个合集当中不包含某个合集值的新合集。

let set1: Set = [1, 2, 3, 4, 5, 5, 6, 4]
let set2: Set = [1, 2, 3, 8, 9, 0]

print(set1.intersection(set2)) // 共同部分
// [2, 1, 3]

print(set1.symmetricDifference(set2)) // 不同部分
// [6, 4, 5, 9, 0, 8]

print(set1.union(set2)) // 两者不重复结合
// [2, 6, 4, 3, 5, 9, 1, 0, 8]

print(set1.subtracting(set2)) // 1中不包含2的部分
// [6, 4, 5]

合集成员关系和相等性

WX20180301-172020@2x.png

使用“相等”运算符 ( == )来判断两个合集是否包含有相同的值;
使用 isSubset(of:) 方法来确定一个合集的所有值是被某合集包含;
使用 isSuperset(of:)方法来确定一个合集是否包含某个合集的所有值;
使用 isStrictSubset(of:) 或者 isStrictSuperset(of:)方法来确定是个合集是否为某一个合集的子集或者超集,但并不相等;
使用 isDisjoint(with:)方法来判断两个合集是否拥有完全不同的值。

字典

Swift 的字典类型写全了是这样的: Dictionary<Key, Value>,其中的 Key是用来作为字典键的值类型, Value就是字典为这些键储存的值的类型。

字典的 Key类型必须遵循 Hashable协议,就像合集的值类型。

var namesOfIntegers = [Int: String]()

namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type [Int: String]

var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

修改字典

airports["LHR"] = "London"
updateValue(_:forKey:)方法会在键没有值的时候设置一个值,或者在键已经存在的时候更新它。
if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
    print("The old value for DUB was \(oldValue).")
}

你可以使用下标脚本语法给一个键赋值 nil来从字典当中移除一个键值对:

airports["APL"] = nil

使用 removeValue(forKey:)来从字典里移除键值对。

if let removedValue = airports.removeValue(forKey: "DUB") {
    print("The removed airport's name is \(removedValue).")
} else {
    print("The airports dictionary does not contain a value for DUB.")
}

可以通过访问字典的 keys和 values属性来取回可遍历的字典的键或值的集合。

Swift 的 Dictionary类型是无序的。要以特定的顺序遍历字典的键或值,使用键或值的 sorted()方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容