我习惯于Python的defaultdict的一种模式是字典,如果未显式设置给定键的值,则该字典将返回默认值。尝试在Swift中做到这一点有点冗长。
var dict = Dictionary<String, Array<Int>>() let key = "foo" var value: Array<Int>! = dict[key] if value == nil { value = Array<Int>() dict[key] = value }
我意识到我可以创建一个做到这一点的类,但是随后必须通过属性访问实际的Dictionary才能使用其他任何普通的Dictionary方法
class DefaultDictionary<A: Hashable, B> { let defaultFunc: () -> B var dict = Dictionary<A, B>() init(defaultFunc: () -> B) { self.defaultFunc = defaultFunc } subscript(key: A) -> B { get { var value: B! = dict[key] if value == nil { value = defaultFunc() dict[key] = value } return value } set { dict[key] = newValue } } }
有更好的模式吗?
使用Swift 2,您可以实现类似于python版本的扩展名Dictionary:
Dictionary
// Values which can provide a default instance protocol Initializable { init() } extension Dictionary where Value: Initializable { // using key as external name to make it unambiguous from the standard subscript subscript(key key: Key) -> Value { mutating get { return self[key, or: Value()] } set { self[key] = newValue } } } // this can also be used in Swift 1.x extension Dictionary { subscript(key: Key, or def: Value) -> Value { mutating get { return self[key] ?? { // assign default value if self[key] is nil self[key] = def return def }() } set { self[key] = newValue } } }
后面的闭包??用于类,因为它们不传播其值突变(仅“指针突变”;引用类型)。
??
var为了使用这些下标,词典必须是可变的():
var
// Make Int Initializable. Int() == 0 extension Int: Initializable {} var dict = [Int: Int]() dict[1, or: 0]++ dict[key: 2]++ // if Value is not Initializable var dict = [Int: Double]() dict[1, or: 0.0]