小编典典

Swift字典默认值

swift

我习惯于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
        }
    }
}

有更好的模式吗?


阅读 655

收藏
2020-07-07

共1个答案

小编典典

使用Swift 2,您可以实现类似于python版本的扩展名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为了使用这些下标,词典必须是可变的():

// 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]
2020-07-07