Chapter 65: Swift Sets
1. The most important intuition: What problem does a Set solve?
A Set is a collection that guarantees only unique values — no duplicates allowed — and gives you very fast “does this contain X?” answers.
Think of it as:
- A guest list for a party where nobody can enter twice
- A collection of tags on a blog post (you never want “swift, swift, ios”)
- A set of permissions a user has (“read”, “write”, “delete” — no duplicates)
- A collection of unique user IDs in a group chat
Key differences from Array:
| Feature | Array [T] | Set <T> |
|---|---|---|
| Order | Yes (keeps the order you add things) | No — order is not guaranteed |
| Duplicates | Allowed | Not allowed — duplicates ignored |
| Fast “contains X?” | Slow — must look through all items | Very fast — uses hashing |
| Can I get element by index? | Yes — array[3] | No — no indices |
| Typical real question | “What is the 5th item?” | “Does this user have permission X?” |
Golden rule you should memorize forever:
If order matters or duplicates are okay → use Array If uniqueness is required and you often ask “is X in the collection?” → use Set
2. Creating Sets – the most common ways
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// 1. Literal syntax (most readable for small sets) var colors = Set<String>() colors.insert("Red") colors.insert("Green") colors.insert("Blue") colors.insert("Red") // ignored – duplicate // 2. From array (very common – remove duplicates) let tagsArray = ["swift", "ios", "swift", "beginner", "swiftui"] let uniqueTags = Set(tagsArray) // Set(["swift", "ios", "beginner", "swiftui"]) // 3. Empty set with type annotation var activeUsers: Set<Int> = [] // 4. From other collections let numbers = [1, 2, 2, 3, 3, 4] let uniqueNumbers = Set(numbers) // Set([1, 2, 3, 4]) |
3. Most important Set operations (you will use these every day)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
var permissions = Set<String>() // Add permissions.insert("read") permissions.insert("write") permissions.insert("moderate") // Check contains (very fast!) print(permissions.contains("write")) // true print(permissions.contains("delete")) // false // Remove permissions.remove("moderate") // Count & empty print(permissions.count) // 2 print(permissions.isEmpty) // false // Combine sets let adminExtras = Set(["delete", "ban", "edit"]) let allPermissions = permissions.union(adminExtras) // Intersection (common permissions) let shared = permissions.intersection(adminExtras) // Difference (what admin has extra) let adminOnly = adminExtras.subtracting(permissions) // Symmetric difference (items in one but not both) let different = permissions.symmetricDifference(adminExtras) |
4. Real-life examples — code you will actually write
Example 1 – User permissions / roles (very common)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
var currentUserRoles = Set<String>() // Load from server / token currentUserRoles.insert("user") currentUserRoles.insert("moderator") currentUserRoles.insert("user") // ignored // Check capabilities if currentUserRoles.contains("moderator") { print("User can moderate posts") } if currentUserRoles.isSuperset(of: ["user", "moderator"]) { print("User has both user and moderator rights") } // Add new role currentUserRoles.insert("admin") // Remove role currentUserRoles.remove("user") |
Example 2 – Unique tags / categories (blog, photo app, product filters)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
var selectedTags = Set<String>() func toggleTag(_ tag: String) { if selectedTags.contains(tag) { selectedTags.remove(tag) print("Tag removed: \(tag)") } else { selectedTags.insert(tag) print("Tag added: \(tag)") } } toggleTag("Swift") toggleTag("iOS") toggleTag("Swift") // does nothing — already present toggleTag("Beginner") print("Active filters:", selectedTags) // Active filters: Set(["Swift", "iOS", "Beginner"]) |
Example 3 – Remove duplicates from user input
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
let userEnteredEmails = [ "rahul@example.com", "priya@gmail.com", "rahul@example.com", "aarav@work.com", "priya@gmail.com" ] let uniqueEmails = Set(userEnteredEmails) print("Unique email addresses:") for email in uniqueEmails { print(" • \(email)") } |
Example 4 – Check required permissions before action
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
let requiredPermissions: Set<String> = ["read", "write", "moderate"] let userHas = Set(["read", "write"]) if userHas.isSuperset(of: requiredPermissions) { print("User has all required permissions") } else { let missing = requiredPermissions.subtracting(userHas) print("Missing permissions: \(missing)") } |
5. Very Common Beginner Mistakes & Correct Habits
| Mistake | Wrong / Dangerous code | Correct / Better habit | Why? |
|---|---|---|---|
| Expecting order in Set | print(mySet) assuming order | Never rely on order in Set | Sets are unordered (can change) |
| Using Set when order matters | let steps = Set([“step1”, “step2”]) | Use Array when order is important | Set will lose order |
| Using Set when duplicates are allowed | let cart = Set([“milk”, “bread”, “milk”]) | Use Array for shopping cart | Set removes duplicates |
| Forgetting Set is value type | var a = b; a.insert(“x”) → b changes? | No — a is copy, b unchanged | Value type safety |
| Checking contains with Array instead of Set | array.contains(“tag”) in hot path | Convert to Set if you check contains often | Array is O(n), Set is O(1) |
6. Quick Summary – When to choose Set vs Array vs Dictionary
| You want to… | Choose this | Typical real-life sentence | Example real use-case |
|---|---|---|---|
| Keep order, allow duplicates | Array | “I have a list of things in order” | shopping cart, messages, tasks, search results |
| Ensure uniqueness, fast “contains?” | Set | “I have a group of unique items” | tags, permissions, unique IDs, friends (no dupes) |
| Fast lookup by key | Dictionary | “I want to find value by name/ID” | user profile, settings, JSON, config |
7. Small Practice – Try these right now
- Create a Set of 6 tags (add some duplicates on purpose) → Print how many unique tags you have → Check if “Swift” is present → Add 2 more tags → Remove one tag
- Create array of 10 email addresses (some duplicates) → Convert to Set to get unique emails → Print how many unique emails were found
- Create a Set of user roles/permissions → Check if user has both “read” and “write” → Check if user has “admin” or “moderator”
Paste your code here if you want feedback, corrections, or more polished versions!
What would you like to explore next?
- Set operations in depth (union, intersection, difference, symmetric difference)
- Array slicing & memory behavior
- Sorting arrays (simple & custom comparators)
- Dictionaries in depth (typed keys, default values)
- Collections in SwiftUI (List, ForEach, @State)
- Or move to another topic (optionals, switch, functions…)
Just tell me — we’ll continue in the same clear, patient, detailed style 😊
