Dictionary subscript or operator which adds a specified "default" value if key doesn't exist is Swift?

53 views Asked by At

I need to write something like the following:

var dict = [SomeEnum: SomeObject]()
var someValue: SomeObject! = dict[.case1]
if someValue == nil {
  someValue = someDefaultValue
  dict[.case1] = someValue
}

The Nil-coalescing operator already exists but it doesn't mutate the original dictionary. The same is for dict[.case1, default: someDefaultValue.

Could you please explain how to write a new subscript/operator to wrap the code above?

1

There are 1 answers

0
Dávid Pásztor On BEST ANSWER

You can create custom subscripts by declaring a new method using the subscript keyword instead of the func keyword.

Based on your requirements, it seems you only need your custom subscript to have a getter, you don't need a setter for it - you can use the default setter to set values.

extension Dictionary {
  /// Subscript which returns the previously set `Value` for `key` in case such value exists.
  /// Otherwise, sets `defaultValue` as the value for `key` and returns `defaultValue`.
  subscript(_ key: Key, defaultValue defaultValue: Value) -> Value {
    mutating get {
      // In case the dictionary already contained a value for key, return the existing value
      if let value = self[key] {
        return value
      } else { // Otherwise, set the key to have defaultValue as its value and return defaultValue
        self[key] = defaultValue
        return defaultValue
      }
    }
  }
}

Usage example:

let defaultValue = "default"
var dict = [Int:String]()
dict[0] = "0"
dict[2] = "2"
let valueFor1 = dict[1, defaultValue: defaultValue] // "default"
print(dict) // [0: "0", 1: "default", 2: "2"]
dict[2, defaultValue: defaultValue] // this returns 2 as the key had a previously set value