《Swift进阶》内建集合类型 字典

Swift 中另外一个关键的数据结构就是Dictionary,字典。字典包含键以及对应的值。在一个字典中,每个键都只能出现一次。通过键来取值所花费的平均时间是常量级的(数组中寻找特定的元素花的时间与它的数组的尺寸成正比)。和数组不同的是字典是无序的,遍历字典的键值对时,顺序是不确定的。

我们可以用下标来获取值(比如dict[“Name”]),字典查找将返回可选值,不存在的时候返回nil。这里和数组不同,使用越界下标访问程序将会崩溃。

字典是一种稀疏结构,即使在name键下有值,你也没办法确定address键下面是否有值。

可变性

和数组一样,使用let定义的字典是不可变的,不能进行添加、修改、删除操作。如果需要操作,就需要用var来进行声明。

删除字典中一个键的值可以使用removeValue(forKey:)方法,也可以使用nil进行赋值。

三个有用的扩展

字典合并

我们的App通常会有设置功能,默认情况下会有一个默认配置,用户也可以自己改变设置用来覆盖默认设置,这个时候使用字典合并是一种很好的解决方法。

在标准库中字典默认没有合并函数,我们需要扩展Dictionary类型,为它添加一个 merge 方法,该方法接受合并的字典作为参数。我们对参数有要求,首先必须是一个序列(Sequence),而且 Iterator.Element 是 (Key,Value)。

扩展代码如下:

extension Dictionary {
// 合并字典
mutating func merge<s>(_ other:S) where S:Sequence , S.Iterator.Element == (key:Key, value:Value){
for (k,v) in other{
self[k] = v
}
}
}</s>

enum Setting{
case text(String)
case int(Int)
case bool(Bool)
}

let defaultSettings : [String:Setting] = [
"Airplane Mode":.bool(true),
"Name":.text("My iPhone"),
]
var settings = defaultSettings
print(settings) // ["Name": Setting.text("My iPhone"), "Airplane Mode": Setting.bool(true)]

var overriddenSettings : [String:Setting] = ["Name":.text("Zmsky's iPhone20")]
settings.merge(overriddenSettings)

print(settings) // ["Name": Setting ctpwjdh.text("Zmsky\'s iPhone20"), "Airplane Mode": Setting.bool(true)]

序列转换成字典

可以利用一个范围转变(Array(1…10))转为数组,也可以讲一个ArraySlice转换回数组(Array(someSlice)),但是字典并没有这样(至少现在)的初始化方法,所以 就只有自己动手写一个了。

extension Dictionary{
init(_ sequence:S) where S.Iterator.Element == (key:Key,value:Value){
self = [:] // 创建一个空字典
self.merge(sequence) // 使用上面的合并方法
}
}

let defaultAlarms = (1..<5).map{ (key:"Alarm\($0)",value:false) }
let alarmsDictionary = Dictionary(defaultAlarms)
print(defaultAlarms) // [("Alarm1", false), ("Alarm2", false), ("Alarm3", false), ("Alarm4", false)]
print(alarmsDictionary) // ["Alarm3": false, "Alarm2": false, "Alarm1": false, "Alarm4": false]

MapValue

我们要添加第三个有用的扩展是一个map函数,它可以用来操作并转换字典中的值。因为Dictionary已经是一个Sequence类型,所以它已经有了一个map函数来产生数组。不过我们有的时候想要的结果是保持字典的结构,只对值进行映射。

流程:对Dictionary先进行map,然后在使用上面的初始化方法转回字典。

// map 不改变字典类型结构
extension Dictionary {
func mapValues(transform:(Value)->(NewValue)) -> [Key:NewValue]{
return Dictionary<Key,NewValue>(map({ (key,value) in
return (key,transform(value))
}))
}
}

let settingsAsString = settings.mapValues { setting -> String in
switch setting{
case .text(let text):return text
case .int(let number):return String(number)
case .bool(let value):return String(value)
}
}
print(settingsAsString) // ["Name": "Zmsky\'s iPhone20", "Airplane Mode": "true"]

Zmsky

http://xloli.net/?page_id=11

在 “《Swift进阶》内建集合类型 字典” 上有 1 条评论

发表评论