Dictionaries
What you'll learn:
- find a value by its key and tell a missing key from a zero;
- add, change and remove the pairs of a dictionary;
- loop over a dictionary in key order and count repeats with
default:; - keep values without repeats in a set and compare two sets.

Picture a phone book. To call Boris, you don't try to remember which line he is on. You find the name and read the number next to it. Each name in the book has one number.
The array from the previous theme works differently: it can hand over an element at once only by its index. If all you know is a name, you have to check the array from the start until the name turns up. For lookups by name, Swift has another collection.
A dictionary stores pairs and finds a value by its key. In a phone book the key is a name, and the value is a phone number:
var phones = ["Anna": "555-1234", "Boris": "555-9876"]
print(phones.count) // 2
print(phones["Anna"] ?? "none") // 555-1234
print(phones["Gleb"] ?? "none") // noneLet's walk through the program line by line:
- The first line creates a dictionary of two pairs. Each pair is written as
key: value, the pairs are separated by commas, and the whole list sits in square brackets. phones.countis the number of pairs in the dictionary, here2.phones["Anna"]finds Anna's number, and the program prints555-1234.- The key
"Gleb"is not in the dictionary. The lookup finds nothing, and??puts the string"none"in place of the answer.
The dictionary type
Swift infers a dictionary's type from its pairs, the way it infers a variable's type from its value. The type of phones is written [String: String]: in square brackets, the key type, a colon and the value type.
What to know about keys and values:
- all keys of one dictionary have one type, and so do all values: in
[String: Int]the keys are strings and the values are integers; - keys never repeat: one name in the book has one number;
- values may repeat: two people are free to leave the same home number;
- an empty dictionary is written
[:], but then you state the type yourself:var ages: [String: Int] = [:].
A lookup gives an optional
A lookup by key may find nothing. That is why phones["Anna"] returns not a String but an optional String?—a box that holds a number or nothing at all. You open it the same ways as any optional: with ?? or if let.
if let number = phones["Boris"] {
print("Boris:", number) // Boris: 555-9876
}The block inside if runs only if the key "Boris" was found. Inside the block, number is a plain string, with no question mark.
Interviewers like to ask what happens when you look up a key that is not in the dictionary. The answer: a lookup of a missing key gives nil, while an index past the end of an array crashes the program.
A missing key is not the same as a zero. If a [String: Int] dictionary holds the pair "Vera": 0, a lookup of "Vera" gives a box with 0, and ?? returns that 0, not the default value. You get nil only when the key is not in the dictionary.
Add, change, remove
A dictionary in a var changes through the same square-bracket form. A dictionary in a let can't be changed: if phones were a constant, the compiler would answer cannot assign through subscript: 'phones' is a 'let' constant.
What an assignment does depends on the key and on the value on the right:
phones["Vera"] = "555-0000"
phones["Anna"] = "555-1111"
phones["Boris"] = nil
print(phones.count) // 2
print(phones["Anna"] ?? "none") // 555-1111
print(phones["Boris"] ?? "none") // noneAdd a pair
The key "Vera" was not in the dictionary, so phones["Vera"] = "555-0000" adds a new pair.
Change a value
The key "Anna" is already there, so phones["Anna"] = "555-1111" replaces the old number with the new one. No second pair with the key "Anna" appears.
Remove a pair
phones["Boris"] = nil removes the whole pair, and a lookup of "Boris" now gives nil. That is why print(phones.count) prints 2: Vera's pair was added, and Boris's pair was removed.
Pairs have no order
Here the phone book picture is inaccurate. In a paper book the names go in alphabetical order, while a Swift dictionary keeps no order of its pairs. The order in which it lists them is not known in advance.
Common mistake
A value from a dictionary is joined to a string without opening the box:
let label = "Anna: " + phones["Anna"] // ✗error: value of optional type 'String?' must be unwrapped to a value of type 'String'The program does not compile: the lookup gives a String?, and a string can be joined only with a String. Open the box first: "Anna: " + (phones["Anna"] ?? "none") gives Anna: 555-1111.
Key points
- A dictionary stores key–value pairs and finds a value by its key; the type
[String: Int]names the key type first, then the value type. - A lookup by key gives an optional: a missing key is
nil, not a crash and not a zero. d[key] = valueadds a pair or changes a value, andd[key] = nilremoves a pair.- Keys in a dictionary never repeat, and a dictionary keeps no order of its pairs.