Swift中的Dictionary,Set,Range

Dictionary,Set,Range

Dictionay的Key

Swift中DictionaryKey都应该是可哈希的,也就是遵守Hashable协议,又因为HashableEquatable的扩展,所以又必须遵守Equatable协议

在Swift中比较两个Type对象(引用相等用===)是否相等,需要遵守Equatable协议,并覆盖==方法,如:

   struct Person {
   var name: String
   var zipCode: Int
   var birthday: Date
}
    extension Person: Equatable {
    static func ==(lhs: Person, rhs: Person) -> Bool {
    return lhs.name == rhs.name
    && lhs.zipCode == rhs.zipCode
    && lhs.birthday == rhs.birthday
    }
}

也就是必须明确一下两点:

  1. 相等的实例必须有相同的哈希值。
  2. 具有相同哈希值的两个对象不一定相等。

由于每次往Dictionary中插入数据,都会判断哈希方法,以确定是否覆盖之前KeyValue。所以这个哈希方法应该具备以下两个特点:

一、应该的执行效率就会影响到对Dictionary的操作效率。
二、哈希方法应该尽可能得减少碰撞。

如上面的Person所示,如果要做为Key就还需要增加下面的代码:

extension Person: Hashable {
  var hashValue:Int {
  returen name.hasValue^zipCode.hashValue^birthday.hashValue
  }
}

注:

  1. 标注库中的基础类型如: String,integer,float,boole,以及没有关联值的Enum。
  2. Dictionary中,如果使用可变的引用类型来作为Key并且将其改变,这个改变同时又改变了哈希值,那么这个Key对应的Value就丢失了。但是如果值类型的实例作为了Key,因为它执行了一次Copy,所以就不用担心被改变了。这也是值类型的一个优势所在。

Set

Set是Swift标准库中唯一遵循SetAlgebra协议的类型(Foundation中的:IndexSet和CharacterSet也遵循该协议),SetAlgebra中提供了subtracting减法,intersection取交集,formUnion取并集,isDisjoint是否有交集等代数方法。IndexSet中存储都是正整数,它和Set相比存储效率更高,因为IndexSet是存储范围的,比如10000中的前500个数只需要存储俩个数值:起点和终点。

在过滤某个数组中的相同元素时候我们往往可以将其放到Set中,这样就可以将相同元素过滤,但是会遇到一个问题,得打的Set和原来的不是顺序不一样,这时,我们可以给Sequence添加Extension来解决。

extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
    var seen:Set<Iterator.Element> = []
    return filter{
        if seen.contains($0){
          return false
        }else{
            seen.insert($0)
            return true
        }
    }
}
}
let result = [1,2,3,12,1,3,4,5,6,4,6].unique()

通过上面的方法就可以将元素按照原来的顺序排列下来。

Range

Swift中管更capable的集合叫countable,countable的边界包含integer和指针。但是不包含浮点型,因为Strideinteger有限制。如果要遍历浮点型数据,那么需要使用stride(from:to:by),以及stride(from:through:by)来新建一个Sequence
将封闭的Ragne转化成半封闭的Range是不可能的,因为在浮点数的情况下不能确定比最大值小的值是多少。 除非这个SequenceStrideable的。如果一个函数接受一个Range座位返回值的话,不可以用...来创建。