Dictionaries & Sets
Reviewed & published by Brayan K
Two more essential collections. By the end of this lesson you'll map keys to values with [K: V] dictionaries (handling optional lookups safely), and use Set for unique values and fast membership tests.
Part of the free Swift course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
- • Declare dictionaries with the [Key: Value] syntax
- • Add, update, and remove key-value pairs
- • Handle optional lookups with if let, ??, and [key, default:]
- • Create Sets for unique, unordered values
- • Combine and compare sets with union, intersection, subtracting
1️⃣ Dictionaries: Key → Value
A dictionary maps unique keys to values, written [Key: Value]. Add or update with subscript assignment. Crucially, looking up a key returns an optional — it's nil when the key isn't present.
// A DICTIONARY maps KEYS to VALUES. Type: [Key: Value].
var ages: [String: Int] = ["Ann": 30, "Ben": 25]
// Add or update with subscript assignment.
ages["Cara"] = 28 // add a new pair
ages["Ann"] = 31 // update an existing key
print(ages.count) // 3
// Looking up a key returns an OPTIONAL (the key might not exist).
let bensAge = ages["Ben"] // Optional(25)
print(bensAge ?? -1) // 25
let unknown = ages["Zed"] // nil — no such key
print(unknown ?? -1) // -1
// Provide a default inline with the subscript:
print(ages["Zed", default: 0]) // 0Unwrap lookups safely and iterate over pairs:
// Safely unwrap a lookup with if let.
let ages = ["Ann": 30, "Ben": 25]
if let a = ages["Ann"] {
print("Ann is \(a)") // Ann is 30
} else {
print("No entry for Ann")
}
// Iterate over (key, value) pairs (order is NOT guaranteed).
for (name, age) in ages.sorted(by: { $0.key < $1.key }) {
print("\(name): \(age)")
}
// Just the keys, or just the values:
print(ages.keys.sorted()) // ["Ann", "Ben"]
// Remove a pair:
var mutable = ages
mutable["Ann"] = nil // assigning nil removes the key
print(mutable.count) // 12️⃣ Sets: Unique & Unordered
A Set<Element> stores each value at most once, with no order. Inserting a duplicate does nothing, which makes sets ideal for de-duplicating and fast contains checks.
// A SET stores UNIQUE, UNORDERED values. Type: Set<Element>.
var tags: Set<String> = ["swift", "ios", "swift"]
print(tags.count) // 2 — the duplicate "swift" collapses
tags.insert("xcode") // add
print(tags.contains("ios")) // true
tags.remove("ios") // remove
print(tags.contains("ios")) // false
// Sets are perfect for de-duplicating an array:
let numbers = [1, 2, 2, 3, 3, 3]
let unique = Set(numbers)
print(unique.count) // 33️⃣ Set Operations
Sets support clean algebra: union (everything), intersection (in both), subtracting (in one but not the other), and symmetricDifference (in exactly one).
// Set algebra: combine and compare sets.
let a: Set = [1, 2, 3, 4]
let b: Set = [3, 4, 5, 6]
print(a.union(b).sorted()) // [1, 2, 3, 4, 5, 6] — everything
print(a.intersection(b).sorted()) // [3, 4] — in BOTH
print(a.subtracting(b).sorted()) // [1, 2] — in a, not b
print(a.symmetricDifference(b).sorted()) // [1, 2, 5, 6] — in exactly one
// Membership and subset checks:
print(a.contains(2)) // true
print(Set([1, 2]).isSubset(of: a)) // trueYour turn. Fill in the blanks, then run it and check the output.
// 🎯 YOUR TURN — replace each ___ then run it in SwiftFiddle.
// 1) A dictionary mapping fruit name -> price.
var prices: [String: ___] = ["apple": 1, "pear": 2] // 👉 value type is Int
// 2) Add a new entry: banana costs 3.
prices["banana"] = ___ // 👉 the number 3
// 3) Safely print the price of "pear" with a default of 0.
print(prices["pear", ___: 0]) // 👉 replace ___ with default
// 4) A set of three colours with one duplicate — print the count.
let colours: Set = ["red", "red", "blue"]
print(colours.___) // 👉 replace ___ with count
// ✅ Expected output:
// 2
// 2Pro Tips
- 💡 Use [key, default: x] to read-with-fallback and even count cleanly: counts[w, default: 0] += 1.
- 💡 De-dupe instantly by wrapping an array in Set(array).
- 💡 Sets are unordered — call .sorted() when you need stable output.
- 💡 Membership is fast. For "is x in this collection?" checks, a Set beats scanning an array.
Common Errors (and the fix)
- "Value of optional type 'Int?' must be unwrapped" — a key lookup is optional. Use if let, ??, or [key, default:].
- Wrong dictionary type syntax — it's [String: Int] (colon), not [String, Int].
- Expecting set order — sets are unordered; relying on iteration order is a bug. Sort first.
- "Cannot use mutating member on immutable value" — insert needs a var set, not a let.
📋 Quick Reference
| Task | Code | Result |
|---|---|---|
| Dictionary | var d: [String: Int] = [:] | empty map |
| Set / update | d["a"] = 1 | add/update key |
| Lookup | d["a"] | Int? (optional) |
| Default | d["a", default: 0] | 0 if missing |
| Set | var s: Set = [1, 2] | unique values |
| Membership | s.contains(1) | true / false |
Mini-Challenge: Vote Counter
Build it, run it, and check your output against the example in the comments.
// 🎯 MINI-CHALLENGE: Vote counter
// 1. Make a var dictionary 'votes' of type [String: Int], starting empty.
// 2. Given let ballots = ["cat", "dog", "cat", "cat", "dog"], loop over it and
// count each: votes[name, default: 0] += 1
// 3. Print each candidate and their tally (sort by key for stable output).
// 4. Make a Set from ballots and print how many UNIQUE options there were.
//
// ✅ Example output:
// cat: 3
// dog: 2
// unique options: 2
// your code here🎉 Lesson Complete!
- ✅ Dictionaries map keys to values with [Key: Value]
- ✅ Key lookups return optionals — handle them with if let, ??, or [key, default:]
- ✅ Sets store unique, unordered values; duplicates collapse
- ✅ Combine sets with union, intersection, subtracting
Practice quiz
How do you write the type of a dictionary mapping String keys to Int values?
- [String, Int]
- Dictionary(String, Int)
- [String: Int]
- {String: Int}
Answer: [String: Int]. Swift dictionary types are written [Key: Value], e.g. [String: Int].
What does looking up a value by key, like dict["x"], return?
- An optional (Value?) — nil if the key is absent
- The value directly
- Always nil
- A Bool
Answer: An optional (Value?) — nil if the key is absent. Subscripting by key returns an optional because the key may not exist.
Why does dictionary key lookup return an optional?
- For speed
- To save memory
- It doesn't — it returns the value
- Because the key might not be present
Answer: Because the key might not be present. A missing key yields nil, so the result type is Value?.
What kind of collection is a Set?
- An ordered list with duplicates
- An unordered collection of unique values
- A key-value map
- A fixed-size array
Answer: An unordered collection of unique values. A Set stores unique, unordered elements.
What happens if you insert a value already in a Set?
- It has no effect — sets keep values unique
- It's added again (duplicate)
- The set is cleared
- It crashes
Answer: It has no effect — sets keep values unique. Sets ignore duplicate insertions, keeping each value only once.
How do you write the type of a Set of Strings?
- [String]
- {String}
- Set<String>
- Set[String]
Answer: Set<String>. A set type is written Set<Element>, e.g. Set<String>.
Which Set method tests membership?
- set.has(x)
- set.contains(x)
- set.includes(x)
- set.member(x)
Answer: set.contains(x). contains(_:) returns a Bool indicating membership.
What does the intersection of two sets contain?
- All elements from both
- Elements in the first but not the second
- Nothing
- Only elements present in BOTH sets
Answer: Only elements present in BOTH sets. intersection keeps only the elements common to both sets.
Are the elements of a Set guaranteed to be in a particular order?
- Yes, insertion order
- No — a Set is unordered
- Yes, sorted order
- Yes, reverse order
Answer: No — a Set is unordered. Sets are unordered; iteration order is not guaranteed.
How do you safely provide a default when a dictionary key is missing?
- dict["k"]!
- dict.get("k")
- dict["k", default: 0]
- dict["k"].orElse(0)
Answer: dict["k", default: 0]. Subscript with a default: dict["k", default: 0] returns 0 if the key is absent.
Continue this course
Frequently asked questions
Why does reading dict[key] give me an optional?
Because the key might not be in the dictionary. Swift can't return a real value when nothing is stored for that key, so the subscript returns Value? — it's nil when the key is absent. Unwrap it with if let, supply a fallback with ??, or use the dict[key, default: x] form to get a non-optional with a default.
What is the difference between an array and a set?
An array is an ordered list that can contain duplicates and is accessed by integer index. A set is an unordered collection of unique values with no indexes — its strength is fast membership testing (contains) and automatically discarding duplicates. Choose a set when order doesn't matter and uniqueness does.
How do I remove a key from a dictionary?
Assign nil to it: dict[key] = nil removes the pair entirely. Alternatively call dict.removeValue(forKey: key), which also returns the removed value (as an optional) if you need it. Setting a key to a real value instead adds or updates that pair.
How can I get the unique elements of an array?
Wrap the array in a Set: let unique = Set(myArray). The set automatically collapses duplicates. If you need an array back (for example to keep working with indexes), convert again with Array(Set(myArray)) — though note the resulting order is not guaranteed.
What do union, intersection, and subtracting do?
These are set operations. union(b) returns all elements in either set; intersection(b) returns only elements present in both; subtracting(b) returns elements in the first set that are not in the second; and symmetricDifference(b) returns elements in exactly one of the two. They make comparing collections concise and readable.