What a dictionary is
A Dictionary stores key-value pairs. You look up a value by its key, the way you look up a phone number by a name, instead of by a position as in an array. Every key is unique and appears once. Values can repeat.
The type is written [KeyType: ValueType]. A dictionary from student names to scores is a [String: Int]: the keys are strings and the values are integers.
Creating a dictionary
There are three common ways to start. The first two give an empty dictionary and the third fills it right away:
var a: [String: Int] = [:]
var b = [String: Int]()
let c = ["Alice": 95, "Bob": 87]
print(a.count, b.count, c.count)
print(type(of: c))
0 0 2
Dictionary<String, Int>
The literal [:] is an empty dictionary and [] is an empty array, so the colon matters. An empty literal has no entries to infer the types from, which is why the first form states the type and the second writes it before the parentheses. A literal with entries, like the third, lets Swift infer [String: Int] by itself.
Adding entries
Assign through the subscript with the key in square brackets. If the key is new, the pair is added:
var ages: [String: Int] = [:]
ages["Alice"] = 25
ages["Bob"] = 30
print(ages["Alice"]!)
print(ages.count)
25
2
The dictionary must be a var. A dictionary declared with let cannot be changed after it is created.
Reading ages["Alice"] gives an optional, because the key might be missing. That is why the example adds ! to unwrap it. The next lesson covers reading values safely.
The exercise, step by step
- Declare
scoreswithvarand make it an empty[String: Int]. It must bevarbecause the next step adds entries. - Assign three entries through the subscript:
"Alice"gets 95,"Bob"gets 87 and"Charlie"gets 72.
var scores = [String: Int]()
scores["Alice"] = 95
scores["Bob"] = 87
scores["Charlie"] = 72
Afterwards scores.count is 3.
Looping over a dictionary
A for loop over a dictionary yields one key-value pair per pass, which you can unpack into two names. Sorting the keys first gives the same order every time:
let scores = ["Alice": 95, "Bob": 87, "Charlie": 72]
for name in scores.keys.sorted() {
print(name, scores[name]!)
}
print(scores.values.reduce(0, +))
Alice 95
Bob 87
Charlie 72
254
Here scores.keys is the collection of keys, sorted() orders them alphabetically, and reduce(0, +) adds up all the values.
Gotchas
- No order. A dictionary does not keep its entries in the order you added them, and printing or looping over one can show them in a different order from run to run. Look up by key, or sort the keys with
scores.keys.sorted()when you need a stable order. - Keys must be unique. Assigning to a key that exists replaces its value instead of adding a second entry.
- Keys must be hashable. Strings, integers and booleans all work as keys.
- Types are fixed. Assigning
scores["Dan"] = "high"is a compile error, since the values are integers.
Dictionaries are copied on assignment
Like arrays, dictionaries are value types. Assigning one to a new variable makes an independent copy, so changing the copy leaves the original alone:
var t = ["Alice": 95, "Bob": 87]
let copy = t
t["Alice"] = 0
print(copy["Alice"]!, t["Alice"]!)
95 0
Key takeaways
- A dictionary maps unique keys to values, written
[KeyType: ValueType]. [:]and[String: Int]()create empty dictionaries, and a dictionary you want to change must be avar.dict[key] = valueadds a new entry or replaces an existing one.
