Swift Dictionaries and Sets

Look up values by key with dictionaries, keep unique values with sets, update and remove entries, loop over them in a predictable order, and count and group data.

Lesson 10 of 43Intermediate18 min read

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

Swift
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 let or give a fallback with ?? or default:.
  • Keys are unique; values can repeat. Keys must be Hashable, which all basic types are.
  • count, isEmpty, keys and values describe the dictionary.

Adding, updating and removing

Swift
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 pattern

Setting 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

Swift
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

Swift
var tags: Set = ["swift", "ios"]
tags.insert("swift")           // ignored: already there
tags.contains("ios")           // true
OperationResult
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:

Swift
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 }
  • mapValues keeps the keys and transforms each value.
  • filter on 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.
  • merging combines 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:

Swift
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)                  // 1

Two 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] = nil removes 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.

Example 1

A price list

Swift
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: ", "))
Output
Sorry, no pizza
Total: £8.75
Menu: cake, coffee, tea
Line-by-line explanation
  1. Line 6Looking up a key returns an optional; if let handles missing items.
  2. Line 13Sorting the keys gives the same order every time.
Example 2

Counting and grouping

Swift
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]!)
}
Output
'the' appears 3 times
A ["Ana", "Alex"]
B ["Ben", "Bella"]
C ["Cy"]
Line-by-line explanation
  1. Line 4default: 0 starts a new word at zero, then += 1 counts it.
  2. Line 6The ! is safe here because the key comes from the dictionary itself.
  3. Line 11grouping builds a dictionary from first letters to arrays of names, keeping their original order.
Example 3

Sets of tags

Swift
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)
Output
Both like: ["design", "swift"]
Anyone likes: ["android", "design", "ios", "kotlin", "swift"]
Only Alice: ["ios"]
Unique pages: 3
Line-by-line explanation
  1. Line 1The type annotation Set makes this a set instead of an array.
  2. Lines 4 to 6Set operations return sets; sorted() turns each into an ordered array for display.
  3. Line 9Converting an array to a Set removes duplicates.

Common Swift Dictionaries Mistakes

Using a dictionary value without unwrapping

Don't
let price: Double = prices["tea"]      // error: value of optional type 'Double?' must be unwrapped
Do
let price = prices["tea"] ?? 0

Relying on dictionary order

Don't
print(prices)                          // order may change between runs
Do
for key in prices.keys.sorted() { print(key, prices[key]!) }

Using an array to check membership in big data

Don't
var seen: [String] = []
if !seen.contains(email) { seen.append(email) }    // slower as it grows
Do
var seen: Set<String> = []
seen.insert(email)                                   // duplicates ignored, fast lookups

Swift 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.

Fill in the blankseasy

Complete the code so it reads the count for "cat", or 0 if it isn't there.

let n = counts["cat", : 0]
Predict the outputeasy

What does this print?

let d = ["a": 1, "b": 2]
print(d["c"] ?? -1)
Predict the outputmedium

What does this print?

var s: Set = [1, 2, 3]
s.insert(2)
s.insert(4)
print(s.count)
Multiple choicemedium

How do you remove the key "cake" from a dictionary?

Multiple choicehard

Why should you sort keys before printing a dictionary in a test?

Swift Dictionaries Quiz

5 questions to check what you learned.

  1. What does reading dict["key"] return?

    • An optional value, nil if the key is missing
    • The value, always
    • The key
    • A Bool
  2. 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
  3. What does Set(["a", "b", "a"]).count return?

    • 3
    • 2
    • 1
    • 0
  4. What does a.intersection(b) return?

    • Everything in either set
    • Items found in both sets
    • Items only in a
    • Items only in b
  5. What must dictionary keys and set items be?

    • Strings
    • Optional
    • Sorted
    • Hashable