Skip to main content

Swift Dictionaries

Introduction

Dictionaries are one of Swift's most versatile collection types, allowing you to store and organize data as key-value pairs. Unlike arrays that use integer indices, dictionaries use keys to access values, making them ideal for scenarios where you need to look up values based on meaningful identifiers.

In this tutorial, you'll learn how to create, access, modify, and iterate through dictionaries in Swift, along with practical applications that will help you understand when and how to use them effectively in your code.

What are Dictionaries?

A dictionary in Swift is a collection of key-value pairs where:

  • Each key is unique within the dictionary
  • Each key maps to exactly one value
  • Keys must be of the same type
  • Values must be of the same type
  • Keys must be hashable (conforming to Swift's Hashable protocol)

Think of a dictionary like a real-world dictionary where you look up a word (the key) to find its definition (the value).

Creating Dictionaries

Basic Syntax

Here's the basic syntax for creating a dictionary in Swift:

swift
var dictionaryName: [KeyType: ValueType] = [key1: value1, key2: value2, key3: value3]

Creating an Empty Dictionary

You can create an empty dictionary in two ways:

swift
// Method 1: Using type annotation
var emptyDictionary1: [String: Int] = [:]

// Method 2: Using initializer syntax
var emptyDictionary2 = [String: Int]()

print(emptyDictionary1) // Output: [:]
print(emptyDictionary2) // Output: [:]

Creating a Dictionary with Initial Values

swift
// Dictionary of student names and their scores
var studentScores = ["Anna": 85, "Brian": 92, "Craig": 78]
print(studentScores)
// Output: ["Craig": 78, "Anna": 85, "Brian": 92]
// Note: Dictionary order is not guaranteed

Dictionary with Different Value Types

swift
// Dictionary with String keys and Any values
var userInfo: [String: Any] = [
"name": "John Doe",
"age": 30,
"isStudent": true,
"grades": [95, 89, 92]
]

print(userInfo)
// Output: ["name": "John Doe", "age": 30, "grades": [95, 89, 92], "isStudent": true]

Accessing Dictionary Values

Using Subscript Notation

You can access dictionary values using their keys in square brackets:

swift
let studentScores = ["Anna": 85, "Brian": 92, "Craig": 78]

// Accessing a value
let annaScore = studentScores["Anna"]
print("Anna's score: \(annaScore)")
// Output: Anna's score: Optional(85)

Notice that accessing a dictionary value returns an optional, because the key might not exist in the dictionary.

Safely Unwrapping Dictionary Values

swift
if let brianScore = studentScores["Brian"] {
print("Brian's score: \(brianScore)")
} else {
print("No score found for Brian")
}
// Output: Brian's score: 92

// Using a default value if the key doesn't exist
let davidScore = studentScores["David"] ?? 0
print("David's score: \(davidScore)")
// Output: David's score: 0

Modifying Dictionaries

Adding or Updating Values

swift
var studentScores = ["Anna": 85, "Brian": 92, "Craig": 78]

// Adding a new key-value pair
studentScores["David"] = 88
print(studentScores)
// Output: ["Craig": 78, "Anna": 85, "Brian": 92, "David": 88]

// Updating an existing value
studentScores["Anna"] = 90
print(studentScores)
// Output: ["Craig": 78, "Anna": 90, "Brian": 92, "David": 88]

Using the updateValue(_:forKey:) Method

This method updates the value for a key and returns the old value (if any):

swift
var studentScores = ["Anna": 85, "Brian": 92, "Craig": 78]

// Update Craig's score and get the old value
if let oldScore = studentScores.updateValue(82, forKey: "Craig") {
print("Craig's score updated from \(oldScore) to 82")
}
// Output: Craig's score updated from 78 to 82

// Try to update a non-existent entry
if let oldScore = studentScores.updateValue(70, forKey: "Emma") {
print("Emma's score updated from \(oldScore) to 70")
} else {
print("Emma was not in the dictionary, but has been added with score 70")
}
// Output: Emma was not in the dictionary, but has been added with score 70

Removing Key-Value Pairs

You can remove a key-value pair in two ways:

swift
var studentScores = ["Anna": 85, "Brian": 92, "Craig": 78, "David": 88]

// Method 1: Assign nil to the key
studentScores["David"] = nil
print(studentScores)
// Output: ["Craig": 78, "Anna": 85, "Brian": 92]

// Method 2: Use removeValue(forKey:)
if let removedValue = studentScores.removeValue(forKey: "Craig") {
print("Removed \(removedValue) for Craig")
}
// Output: Removed 78 for Craig

print(studentScores)
// Output: ["Anna": 85, "Brian": 92]

Removing All Key-Value Pairs

swift
var studentScores = ["Anna": 85, "Brian": 92]
studentScores.removeAll()
print(studentScores)
// Output: [:]

Dictionary Properties and Methods

Checking Dictionary Size and Content

swift
var fruitInventory = ["apples": 50, "oranges": 32, "bananas": 25]

// Check if dictionary is empty
print(fruitInventory.isEmpty) // Output: false

// Get the number of key-value pairs
print(fruitInventory.count) // Output: 3

// Get all keys
let allFruits = Array(fruitInventory.keys)
print("Available fruits: \(allFruits)")
// Output: Available fruits: ["oranges", "bananas", "apples"]

// Get all values
let allQuantities = Array(fruitInventory.values)
print("All quantities: \(allQuantities)")
// Output: All quantities: [32, 25, 50]

Checking if a Key Exists

swift
let fruitInventory = ["apples": 50, "oranges": 32, "bananas": 25]

if fruitInventory.keys.contains("apples") {
print("We have apples in stock")
}
// Output: We have apples in stock

Iterating Through Dictionaries

Iterating Through Key-Value Pairs

swift
let fruitInventory = ["apples": 50, "oranges": 32, "bananas": 25]

// Iterate through key-value pairs
for (fruit, quantity) in fruitInventory {
print("\(fruit): \(quantity)")
}
// Output:
// oranges: 32
// bananas: 25
// apples: 50

Iterating Through Keys Only

swift
let fruitInventory = ["apples": 50, "oranges": 32, "bananas": 25]

// Iterate through keys
for fruit in fruitInventory.keys {
print(fruit)
}
// Output:
// oranges
// bananas
// apples

Iterating Through Values Only

swift
let fruitInventory = ["apples": 50, "oranges": 32, "bananas": 25]

// Iterate through values
for quantity in fruitInventory.values {
print(quantity)
}
// Output:
// 32
// 25
// 50

Practical Examples

Example 1: Contact Management System

swift
// Create a contacts dictionary
var contacts: [String: [String: Any]] = [
"John": [
"phone": "555-1234",
"email": "[email protected]",
"address": "123 Main St"
],
"Sarah": [
"phone": "555-5678",
"email": "[email protected]",
"address": "456 Oak Ave"
]
]

// Accessing nested dictionary information
if let johnInfo = contacts["John"] {
if let johnEmail = johnInfo["email"] as? String {
print("John's email: \(johnEmail)")
}
}
// Output: John's email: [email protected]

// Adding a new contact
contacts["Mike"] = [
"phone": "555-9012",
"email": "[email protected]",
"address": "789 Pine Rd"
]

// Updating contact information
if var sarahInfo = contacts["Sarah"] {
sarahInfo["phone"] = "555-8765"
contacts["Sarah"] = sarahInfo
}

print("Updated contacts: \(contacts["Sarah"]?["phone"] ?? "No phone")")
// Output: Updated contacts: 555-8765

Example 2: Word Frequency Counter

swift
func countWordFrequency(in text: String) -> [String: Int] {
let words = text.lowercased().components(separatedBy: .whitespacesAndNewlines)
var frequency: [String: Int] = [:]

for word in words {
// Remove punctuation
let cleanWord = word.trimmingCharacters(in: .punctuationCharacters)
if !cleanWord.isEmpty {
frequency[cleanWord, default: 0] += 1
}
}

return frequency
}

let sampleText = "Swift is amazing. Swift is also easy to learn. I love programming in Swift!"
let wordFrequency = countWordFrequency(in: sampleText)

// Sort results by frequency
let sortedResults = wordFrequency.sorted { $0.value > $1.value }

for (word, count) in sortedResults {
print("\(word): \(count)")
}

// Output:
// swift: 3
// is: 2
// to: 1
// programming: 1
// love: 1
// learn: 1
// in: 1
// i: 1
// easy: 1
// also: 1
// amazing: 1

Example 3: Simple Menu Ordering System

swift
// Menu with prices
let menu = [
"burger": 5.99,
"fries": 2.49,
"soda": 1.99,
"salad": 4.49,
"pizza": 8.99
]

// Function to calculate order total
func calculateOrderTotal(items: [String]) -> (total: Double, unavailableItems: [String]) {
var total = 0.0
var unavailableItems: [String] = []

for item in items {
if let price = menu[item] {
total += price
} else {
unavailableItems.append(item)
}
}

return (total, unavailableItems)
}

// Place an order
let order = ["burger", "fries", "soda", "ice cream"]
let (total, unavailableItems) = calculateOrderTotal(items: order)

// Print the order details
print("Order summary:")
if unavailableItems.isEmpty {
print("All items available")
} else {
print("Unavailable items: \(unavailableItems.joined(separator: ", "))")
}
print("Total: $\(String(format: "%.2f", total))")

// Output:
// Order summary:
// Unavailable items: ice cream
// Total: $10.47

Nested Dictionaries

Dictionaries can contain other dictionaries as values, allowing you to create complex data structures:

swift
// A dictionary of dictionaries representing a classroom
var classroom: [String: [String: Any]] = [
"students": [
"John": ["grade": "A", "age": 15],
"Lisa": ["grade": "B", "age": 16],
"Mike": ["grade": "B+", "age": 15]
],
"teachers": [
"Mrs. Smith": ["subject": "Math", "room": 101],
"Mr. Johnson": ["subject": "Science", "room": 102]
]
]

// Accessing nested values
if let students = classroom["students"] as? [String: [String: Any]],
let johnInfo = students["John"] as? [String: Any],
let johnGrade = johnInfo["grade"] as? String {
print("John's grade: \(johnGrade)")
}
// Output: John's grade: A

// Adding a new student
if var students = classroom["students"] as? [String: [String: Any]] {
students["Emma"] = ["grade": "A-", "age": 16]
classroom["students"] = students
}

Dictionary Type Constraints

You can create dictionaries with specific type constraints:

swift
// Dictionary with Int keys and String values
var idToName: [Int: String] = [
1: "John",
2: "Sarah",
3: "Mike"
]

// Dictionary with enum keys
enum Days {
case monday, tuesday, wednesday, thursday, friday
}

var scheduleByDay: [Days: String] = [
.monday: "Math",
.tuesday: "Science",
.wednesday: "History",
.thursday: "English",
.friday: "Art"
]

print("Tuesday's schedule: \(scheduleByDay[.tuesday] ?? "Free")")
// Output: Tuesday's schedule: Science

Common Dictionary Operations

Merging Dictionaries

swift
let firstDict = ["a": 1, "b": 2]
let secondDict = ["b": 3, "c": 4]

// Create a new dictionary by merging two dictionaries
var merged = firstDict.merging(secondDict) { (current, new) in current }
print(merged)
// Output: ["a": 1, "b": 2, "c": 4]

// If we want to keep the new values instead
merged = firstDict.merging(secondDict) { (current, new) in new }
print(merged)
// Output: ["a": 1, "b": 3, "c": 4]

Filtering Dictionaries

swift
let scores = ["John": 85, "Sarah": 92, "Mike": 78, "Emma": 95]

// Filter for scores above 90
let highScorers = scores.filter { $0.value > 90 }
print("High scorers: \(highScorers)")
// Output: High scorers: ["Sarah": 92, "Emma": 95]

Transforming Dictionary Values

swift
let scores = ["John": 85, "Sarah": 92, "Mike": 78, "Emma": 95]

// Convert scores to letter grades
let letterGrades = scores.mapValues { score -> String in
switch score {
case 90...:
return "A"
case 80..<90:
return "B"
case 70..<80:
return "C"
default:
return "F"
}
}

print("Letter grades: \(letterGrades)")
// Output: Letter grades: ["John": "B", "Sarah": "A", "Emma": "A", "Mike": "C"]

Summary

Dictionaries are powerful collections in Swift that allow you to store and retrieve data using key-value pairs. They provide:

  • Efficient lookup of values using keys
  • Flexibility in storing different types of data
  • Methods for adding, updating, and removing entries
  • Support for iterating through keys, values, or key-value pairs

Key takeaways from this tutorial:

  1. Dictionaries store key-value pairs where each key must be unique
  2. Dictionary values are accessed by their keys and return optionals
  3. You can add, update, or remove entries from a dictionary
  4. Dictionaries provide methods for filtering, transforming, and merging
  5. Complex data structures can be created using nested dictionaries

Exercises

  1. Basic Dictionary Practice: Create a dictionary that maps country names to their capital cities. Add at least 5 countries, then print the capital of a specific country.

  2. Dictionary Manipulation: Create a dictionary of grocery items with their prices. Write code to:

    • Add a new item
    • Update the price of an existing item
    • Remove an item
    • Calculate the total price of all items
  3. Word Frequency Counter Enhancement: Enhance the word frequency counter example to:

    • Ignore common words like "the", "a", "and", etc.
    • Sort the results alphabetically for words with the same frequency
  4. Nested Dictionary Challenge: Create a nested dictionary to represent a small library. Each key should be a book title, and each value should be another dictionary containing author, publication year, and genre.

  5. Dictionary Transformation: Create a dictionary of student names and their test scores. Write a function that returns a new dictionary mapping student names to pass/fail status (pass if score >= 60).

Additional Resources

Happy coding with Swift Dictionaries!



If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)