Swift 4.0 中对 Dictionary 的改进(转载)

Swift 4 发布已经有一段时间了,不知道你们有没有切换到 4.0 版本。 此次 4.0 更新给我最大的感觉就是没有了前几回升级的跳跃式变化。 不用为了更新语言版本,彻底推翻已有的项目,这也是 Swift 慢慢趋向于稳定的标志。swift

我们此次说说 Swift 4.0 对 Dictionary 这个常常会用到的类的改进。数组

自动根据 key 分组

Dictionary 新增了一个构造方法,能够将给定的一个数组,根据指定的条件进行分组。 来看一个例子:闭包

struct Person {

    var name: String
    var gender: Gender
    var age: Int

    enum Gender {
        case male
        case female
    }

}
复制代码

这里有一个 Person 结构, 而后咱们初始化一个数组:app

let p1 = Person(name: "aa", gender: .female, age: 22)
let p2 = Person(name: "bb", gender: .male, age: 24)
let p3 = Person(name: "cc", gender: .male, age: 21)

let persons = [p1, p2, p3]
复制代码

如今用新的 Dictionary 构造方法,能够当即将这组 Person 实例根据他们的 gender 属性进行分组:工具

let groupedDict = Dictionary(grouping: persons) { p in

    return p.gender

}
复制代码

这个构造方法,第一个参数 grouping 接收的是 persons 数组, 第二个参数是一个闭包,用于返回根据进行分组的依据,咱们这里返回的是 p.gender。结果一目了然:post

[
    .male: [
        Person(name: "bb", gender: .male, age: 24), 
        Person(name: "cc", gender: .male, age: 21)
    ], 
    .female: [
        Person(name: "aa", gender: .female, age: 22)
    ]
]
复制代码

以往要实现这样的功能,就须要手动遍历整个数组,取出 key, 而后生成字典, 如今方便不少。ui

value 无缝转换

另一个比较有用的特性是,Dictionary 提供的 mapValues 方法。 还以咱们刚才生成的 groupedDict 为例,能够进行这样的操做:spa

let count = groupedDict.mapValues { persons in
    persons.count
}
复制代码

先看一下输出,你们可能就猜到这个方法的用途是什么了:code

[
    .male: 2, 
    .female: 1
]
复制代码

上面的输出能够看到, mapValues 会遍历每个 key 对应的 values, 而后传递给闭包进行自定义转换。 咱们例子中的闭包返回的就是每一个 key 对应的 Person 集合的数量,最生成了一个新的 Dictionary,里面的 key 和以前同样,只是对应的值变成了咱们闭包中自定义的了。blog

mapValues 方法一样是一个帮助咱们解决繁杂操做的工具方法。

从键值对元组中直接构建

假如咱们有这样一个数组:

let personsTuples = [("group 1", [p1, p2]),  ("group 2", [p3])]
复制代码

而后能够调用 uniqueKeysWithValues 构造方法直接初始化字典:

let dict = Dictionary(uniqueKeysWithValues: personsTuples)
复制代码

personsTuples 数组中,每个元素都是一个元组(Tuple), 这个构造方法把元组中的第一项当作 key, 第二项当作 value, 生成一个新的 Dictionary,以下所示:

[
    "group 1": [
        Person(name: "aa", gender: .female, age: 22), 
        Person(name: "bb", gender: .male, age: 24)
    ], 
    "group 2": [
        Person(name: "cc", gender: .male, age: 21)
    ]
]
复制代码

使用 uniqueKeysWithValues 构造方法时候须要注意,就是传入的数组中,不能有重复的 key, 不然会报运行时错误,好比这个数组就会报错:

let personsTuples = [("group 1", [p1, p2]),  ("group 2", [p3]), ("group 2", [p4])]
复制代码

上面数组中 group 2 出现了两次。 若是用它来初始化的话,就会出错。 因此 Swift 4.0 还提供了另一个初始化方法, 对于上面这个数组,能够调用:

let dict = Dictionary(personsTuples) { old, new in
    return new
}
复制代码

第二个闭包参数,会在遇到重复的 key 时候调用。 它提供两个参数,一个是一样这个 key 的上一个值 old, 还有当前的值 new。 咱们这里直接返回 new,意思就是 每次遇到重复的 key, 就用新的值代替老的值。 这样初始化后,生成的 Dictionary 结构以下:

[
    "group 1": [
            p1,
            p2
    ], 
    "group 2": [
            p4
    ]
]
复制代码

group 2 中的值, 是第二次 key 所对应的 p4。

提供默认值

若是咱们访问了一个字典中不存在的 key, 会返回 nil:

dict["group 3"]
复制代码

由于上面字典中,不存在 group 3 这个 key, 因此它返回了 nil。 Swift 4 中新增了指定默认值的能力:

dict["group 3", default: []]
复制代码

这样调用,若是 group 3 这个 key 不存在的话, 就会返回咱们指定的默认值空数组, 而不是 nil 了。 这个特性在咱们处理 JSON 数据解析这类的问题上很实用。

过滤器

过滤器对于集合类来讲是比较经常使用的功能。 Swift 4 中对 Dictionary 类型也提供了过滤器的支持:

let filteredDict = dict.filter { key, val in

    return val.count >= 2

}
复制代码

filter 方法接收一个闭包,它会遍历 Dictionary 中全部的元素,而且做为闭包的参数传入。 咱们须要经过闭包的返回值肯定这个元素是否被保留。 上面的例子中,好比咱们 dict 中的元素是 :

[
    "group 1": [
            p1,
            p2
    ], 
    "group 2": [
            p4
    ]
]
复制代码

调用 filter 后,咱们只保留数量大于 2 的集合:

[
    "group 1": [
            p1,
            p2
    ]
]
复制代码

总结

以上就是 Swift 4.0 对于 Dictionary 的主要改进。 这些新增的工具方法对于提升咱们开发效率和代码质量都有帮助,但愿这里的介绍对你有帮助。 关于 Dictionary 更完整的信息,你们还能够参考苹果官方的文档,还有 Swift Blog 中的介绍。

参考文献

Dictionary 官方文档:https://developer.apple.com/documentation/swift/dictionary

Swift Blog: https://swift.org/blog/dictionary-and-set-improvements/

转载自:http://swiftcafe.io/post/swift4-dict

相关文章
相关标签/搜索