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()方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容