Arrays are perfect for ordered lists, but often you need to look something up: a word's translation, a product's price by its code, a contact's number by their name. A dictionary stores key-value pairs and finds a value by its key almost instantly, however many entries there are.
A set answers a different question: "is this here?". It stores unique values, ignoring duplicates, and checks membership very quickly. Sets are ideal for tags, selected items, visited places, or removing duplicates from a list.
One important detail: dictionaries and sets are unordered. When you print or loop over them, the order can differ from run to run. In this lesson you'll read and update dictionaries safely, loop over them in a predictable order, count and group data, and combine sets with union and intersection.
Creating and reading dictionaries
var prices = ["tea": 2.5, "cake": 3.75] // [String: Double]
var empty: [String: Int] = [:]
let tea = prices["tea"] // Optional(2.5)
let pizza = prices["pizza"] // nil
let cost = prices["pizza", default: 0] // 0.0- The type
[String: Double]means keys are Strings and values are Doubles. - Reading by key returns an optional, because the key might not exist. Unwrap it with
if letor give a fallback with??ordefault:. - Keys are unique; values can repeat. Keys must be Hashable, which all basic types are.
count,isEmpty,keysandvaluesdescribe the dictionary.
Adding, updating and removing
prices["soup"] = 4.0 // add
prices["tea"] = 2.8 // update
prices["cake"] = nil // remove
prices["visits", default: 0] += 1 // not for prices, but a handy counting patternSetting a key adds it if it's new and replaces the value if it exists. Assigning nil removes the key. updateValue(_:forKey:) and removeValue(forKey:) do the same but also return the old value, which is useful when you need to know what was there.
Looping in a stable order
for (item, price) in prices {
print("\(item): \(price)") // order not guaranteed
}
for item in prices.keys.sorted() {
print("\(item): \(prices[item]!)") // alphabetical every time
}Because dictionaries are unordered, sort the keys (or the pairs, with sorted { $0.key < $1.key }) whenever order matters, such as for display or tests. Dictionary(grouping: items, by: { $0.category }) builds a dictionary of arrays, grouping items by any property.
Sets
var tags: Set = ["swift", "ios"]
tags.insert("swift") // ignored: already there
tags.contains("ios") // true| Operation | Result |
|---|---|
a.union(b) | Everything in either set |
a.intersection(b) | Items in both |
a.subtracting(b) | Items in a but not b |
a.isSubset(of: b) | true if every item of a is in b |
Set(array) | Removes duplicates from an array |
To display a set in a predictable order, sort it: tags.sorted().
Transforming whole dictionaries
Several methods work on every entry at once and return a new dictionary:
let prices = ["tea": 2.5, "cake": 3.75, "soup": 4.0]
let withTax = prices.mapValues { $0 * 1.2 } // same keys, new values
let cheap = prices.filter { $0.value < 3.5 } // ["tea": 2.5]
let menu = Dictionary(uniqueKeysWithValues: zip(["a", "b"], [1, 2]))
let updated = ["a": 1, "b": 2].merging(["b": 20, "c": 3]) { old, new in new }mapValueskeeps the keys and transforms each value.filteron a dictionary returns a dictionary of the entries that pass.Dictionary(uniqueKeysWithValues:)builds one from pairs. It crashes if a key appears twice, so only use it when keys are guaranteed unique.mergingcombines two dictionaries, and its closure decides which value wins when both have the same key. Here the new value 20 replaces 2.
Your own types as keys and set items
Dictionary keys and set items must be Hashable: Swift needs to turn each one into a number, called a hash, to find it instantly. Strings, numbers and Bools already are. For your own struct, add Hashable and Swift writes the code for you, as long as every property is Hashable too:
struct Point: Hashable {
var x: Int
var y: Int
}
var visited: Set<Point> = [Point(x: 0, y: 0)]
visited.insert(Point(x: 0, y: 0)) // ignored: an equal point is there
print(visited.count) // 1Two points with the same x and y count as the same item. This is a common way to track which squares of a game board you've already visited.
Swift Dictionaries Syntax
Dictionaries and sets
var d = ["a": 1, "b": 2]
d["a"] d["z", default: 0] d.keys d.values d.count
d["c"] = 3 d["a"] = nil
for (k, v) in d { }
for k in d.keys.sorted() { }
d[k, default: 0] += 1
Dictionary(grouping: items, by: { $0.type })
var s: Set = [1, 2, 3]
s.insert(4) s.contains(2) s.union(t) s.intersection(t) s.subtracting(t)Swift Dictionaries Summary
[Key: Value]dictionaries look up values by unique keys; reading returns an optional.dict[key, default: x]reads with a fallback;dict[key] = nilremoves an entry.- Dictionaries and sets are unordered; sort keys or items for stable output.
- Dictionary(grouping:by:) groups items; the default subscript makes counting easy.
- Sets hold unique values and support union, intersection, subtracting and fast contains.
Swift Dictionaries Examples
Each example shows the code, the output it produces and what each part does.
A price list
let menu = ["tea": 2.5, "coffee": 2.8, "cake": 3.75]
let order = ["tea", "cake", "pizza", "tea"]
var total = 0.0
for item in order {
if let price = menu[item] {
total += price
} else {
print("Sorry, no \(item)")
}
}
print("Total: £\(total)")
print("Menu:", menu.keys.sorted().joined(separator: ", "))Sorry, no pizza
Total: £8.75
Menu: cake, coffee, teaLine-by-line explanation
- Line 6Looking up a key returns an optional; if let handles missing items.
- Line 13Sorting the keys gives the same order every time.
Counting and grouping
let text = "the cat sat on the mat the end"
var counts: [String: Int] = [:]
for word in text.split(separator: " ") {
counts[String(word), default: 0] += 1
}
for word in counts.keys.sorted() where counts[word]! > 1 {
print("'\(word)' appears \(counts[word]!) times")
}
let names = ["Ana", "Ben", "Alex", "Bella", "Cy"]
let byLetter = Dictionary(grouping: names, by: { $0.first! })
for letter in byLetter.keys.sorted() {
print(letter, byLetter[letter]!)
}'the' appears 3 times
A ["Ana", "Alex"]
B ["Ben", "Bella"]
C ["Cy"]Line-by-line explanation
- Line 4default: 0 starts a new word at zero, then += 1 counts it.
- Line 6The ! is safe here because the key comes from the dictionary itself.
- Line 11grouping builds a dictionary from first letters to arrays of names, keeping their original order.
Sets of tags
let alice: Set = ["swift", "ios", "design"]
let bob: Set = ["swift", "android", "design", "kotlin"]
print("Both like:", alice.intersection(bob).sorted())
print("Anyone likes:", alice.union(bob).sorted())
print("Only Alice:", alice.subtracting(bob).sorted())
let visits = ["home", "shop", "home", "cart", "shop"]
print("Unique pages:", Set(visits).count)Both like: ["design", "swift"]
Anyone likes: ["android", "design", "ios", "kotlin", "swift"]
Only Alice: ["ios"]
Unique pages: 3Line-by-line explanation
- Line 1The type annotation Set makes this a set instead of an array.
- Lines 4 to 6Set operations return sets; sorted() turns each into an ordered array for display.
- Line 9Converting an array to a Set removes duplicates.
Common Swift Dictionaries Mistakes
Using a dictionary value without unwrapping
let price: Double = prices["tea"] // error: value of optional type 'Double?' must be unwrappedlet price = prices["tea"] ?? 0Relying on dictionary order
print(prices) // order may change between runsfor key in prices.keys.sorted() { print(key, prices[key]!) }Using an array to check membership in big data
var seen: [String] = []
if !seen.contains(email) { seen.append(email) } // slower as it growsvar seen: Set<String> = []
seen.insert(email) // duplicates ignored, fast lookupsSwift Dictionaries in Real Projects
Dictionaries and sets in apps
Apps cache downloaded images in dictionaries keyed by URL, store translated text keyed by identifiers, and decode JSON objects into dictionaries or structs. Sets track which photos a user has selected, which notifications they've already seen, or which features are switched on. Because lookups are so fast, they keep apps responsive even with thousands of items.
Swift Dictionaries FAQ
Why does a Swift dictionary return an optional?
The key you ask for might not be in the dictionary, so prices["pizza"] returns Double? and gives nil when the key is missing. Unwrap it with if let, use ??, or use prices["pizza", default: 0] to get a plain value.
How do I sort a dictionary by value in Swift?
Dictionaries have no order of their own, but sorted returns an array of key-value pairs in any order you choose: prices.sorted { $0.value < $1.value }. Loop over the result and use .key and .value on each pair.
What is the difference between a Set and an Array in Swift?
An array keeps items in order, allows duplicates and is read by position. A set has no order, keeps every item unique, and checks whether it contains something almost instantly. Use a set when membership matters more than order.
How do I count occurrences of items in Swift?
Loop through the items and increase a counter in a dictionary using a default: counts[word, default: 0] += 1. Each new key starts at 0 automatically, so no separate check is needed.
How do I check if a key exists in a Swift dictionary?
Test the lookup against nil: if prices["tea"] != nil. If you also want the value, use if let price = prices["tea"]. prices.keys.contains("tea") works too but is longer.
Swift Dictionaries Exercises
Answer each one and check it instantly. If you get stuck, open the hint before the answer.
Complete the code so it reads the count for "cat", or 0 if it isn't there.
let n = counts["cat", : 0]
What does this print?
let d = ["a": 1, "b": 2]
print(d["c"] ?? -1)
What does this print?
var s: Set = [1, 2, 3]
s.insert(2)
s.insert(4)
print(s.count)
How do you remove the key "cake" from a dictionary?
Why should you sort keys before printing a dictionary in a test?
Swift Dictionaries Quiz
5 questions to check what you learned.
What does reading
dict["key"]return?- An optional value, nil if the key is missing
- The value, always
- The key
- A Bool
What happens when you insert a duplicate into a set?
- An error
- It's added twice
- Nothing; the set keeps one copy
- The set is cleared
What does
Set(["a", "b", "a"]).countreturn?- 3
- 2
- 1
- 0
What does
a.intersection(b)return?- Everything in either set
- Items found in both sets
- Items only in a
- Items only in b
What must dictionary keys and set items be?
- Strings
- Optional
- Sorted
- Hashable