Sets
Swift Set is an unordered collection of unique, Hashable values. Fast membership, union/intersection/difference, and easy interop with Array.
Swift — Set
EXAMPLE
// ===== Creating a Set =====
var tags: Set<String> = ["vip", "beta", "vip"] // duplicates collapse
print(tags) // unordered
// From an array:
let arr = [1, 2, 2, 3, 4, 4, 5]
let unique = Set(arr) // [1, 2, 3, 4, 5]
// Type inference needs help when Swift can't tell:
let empty = Set<Int>()
let alsoEmpty: Set<Int> = []
// ===== Mutation =====
tags.insert("new") // (inserted: true, memberAfterInsert: "new")
tags.remove("beta") // returns the removed element, or nil
tags.removeAll()
// ===== Membership and counts =====
let s: Set = [1, 2, 3, 4]
s.contains(3) // true
s.count // 4
s.isEmpty // false
// ===== Set algebra =====
let a: Set = [1, 2, 3, 4]
let b: Set = [3, 4, 5, 6]
a.union(b) // [1, 2, 3, 4, 5, 6]
a.intersection(b) // [3, 4]
a.subtracting(b) // [1, 2]
a.symmetricDifference(b)// [1, 2, 5, 6]
// Relationships:
a.isSubset(of: [1,2,3,4,5]) // true
a.isStrictSubset(of: [1,2,3,4]) // false (equal isn't strict)
a.isSuperset(of: [1, 2]) // true
a.isDisjoint(with: [9, 10]) // true
// ===== In-place variants =====
var x: Set = [1, 2, 3]
x.formUnion([3, 4]) // x is now [1,2,3,4]
x.formIntersection([2, 3, 9]) // x is now [2,3]
x.subtract([3]) // x is now [2]
// ===== Custom Hashable types =====
struct User: Hashable {
let id: UUID
let name: String
// Swift synthesises Hashable when all stored properties are Hashable.
}
var members: Set<User> = []
members.insert(User(id: UUID(), name: "Alex"))
// Override hash to consider only id:
struct UserById: Hashable {
let id: UUID
let name: String
func hash(into hasher: inout Hasher) { hasher.combine(id) }
static func == (l: Self, r: Self) -> Bool { l.id == r.id }
}
// ===== Iteration =====
for t in tags {
print(t) // unordered each time
}
// Sort to iterate stably:
for t in tags.sorted() {
print(t)
}
// ===== Bridging =====
let arrayOut = Array(tags) // ordering not guaranteed
let backToSet = Set(arrayOut)
// ===== Filter + map produce arrays; explicitly convert back =====
let evens = a.filter { $0 % 2 == 0 } // [Int]
let evensSet = Set(evens) // Set<Int>
// ===== Patterns to internalise =====
// - Set for any 'distinct membership' collection (tags, ids, flags)
// - Use set algebra over manual loops: a.subtracting(b) beats nested for loops
// - Implement Hashable on identity-only types (override hash + ==) when storage uses ids
// - sorted() when iteration order matters; never rely on Set's order
// ===== Pitfalls =====
// - Treating a Set like an Array — Set has no [] subscript by index
// - Hash collisions caused by lazy/random hash impls -> rare but real on custom types
// - Reordering across runs (Hashable uses a per-process random seed) -> never persist Set iteration order
// - Mixing Hashable with reference types whose hash changes after insert -> 'lost' element
Why it matters
Set is the right tool more often than people remember: unique tags, ids, capability flags, anything where order does not matter. The algebra (union/intersection/subtracting) replaces nested loops with one-liners, and Hashable synthesis means you barely write any boilerplate.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
let tags: Set<String> = ["sql", "postgres", "sql"]
print(tags.contains("sql"))
Try it Yourself »
Discussion
Loading…