Dictionary default value for keys that don't exist

If I have a dictionary such as:

let book: [AnyHashable:Any] = [:]

Is there a way to have any keys that are accessed that don't have a value to return a default value and not nil ?

print(book["key", default: "Unknown"])
1 Like

If you're not editing the dictionary, I'd prefer

book[.init("key")] ?? "Default Value"

@Lantua, do you mean that you’d prefer coalescing over @cukr‘a suggestion? If so, why?

Well, the two codes are identical, so the choice is more of a stylistic one.

Nonetheless, I do prefer ?? over library-specific API since it's what people are more familiar with. One can grok what subscript(_:default:) does, but it's easy to miss that the getter does not write back the default value to the storage (and there are instances of that being a bug IME). If anything, I do use the subscript when there's a write-back involved.

If you're only reading a value, then the two alternatives are identical. However, if you're modifying a value in the dictionary, they are not.

For example, this code:

var scoresForUser: [User: Array<Int>] = [:]

func addScore(_ score: Int, for user: User) {
  if let existingArray = scoresForUser[user] {
    var newArray = existingArray
    newArray.append(score)
    scoresForUser[user] = newArray
  } else {
    scoresForUser[user] = [score]
  }
}

can be dramatically simplified by using the default: subscript, as shown here:

var scoresForUser: [User: Array<Int>] = [:]

func addScore(_ score: Int, for user: User) {
  scoresForUser[user, default:[]].append(score)
}

Because the default value is part of the subscript, you can call a mutating func on it and it will update the dictionary correctly.

But if you're just reading a value, then there's no difference between using subscript(_:default:) and just ?? on the outside.

1 Like

You are correct.

1 Like