Swift
Programming
Arrays
Duplicates
Code Optimization

Removing duplicate elements from an array in Swift

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Removing duplicates from Swift arrays is a common task in API response cleanup, local caching, and UI list preparation. The right technique depends on two key requirements: whether order must be preserved and whether elements are hashable. Efficient deduplication is easy in Swift, but correctness depends on picking the method that matches your data contract.

Core Sections

Use Set conversion for quick uniqueness

If order does not matter, converting to Set is concise and typically fast.

swift
let values = [1, 2, 3, 2, 4, 1, 5]
let unique = Array(Set(values))
print(unique)

This removes duplicates but returns elements in undefined order, so avoid it for UI sequences where order is meaningful.

Preserve order with a tracking set

For ordered output, keep a set of seen values and append only first occurrences.

swift
1func uniquedPreservingOrder<T: Hashable>(_ input: [T]) -> [T] {
2    var seen = Set<T>()
3    var result: [T] = []
4    result.reserveCapacity(input.count)
5
6    for item in input {
7        if seen.insert(item).inserted {
8            result.append(item)
9        }
10    }
11    return result
12}
13
14let ordered = uniquedPreservingOrder(["a", "b", "a", "c", "b"])
15print(ordered) // ["a", "b", "c"]

This pattern is the best default for most app-level deduplication tasks.

Use key-based deduplication for complex objects

Many arrays contain structs or classes where uniqueness depends on one field, such as id. In that case, dedupe by key rather than full object equality.

swift
1struct User {
2    let id: Int
3    let name: String
4}
5
6func uniqueById(_ users: [User]) -> [User] {
7    var seenIds = Set<Int>()
8    return users.filter { user in
9        seenIds.insert(user.id).inserted
10    }
11}
12
13let users = [
14    User(id: 1, name: "Ava"),
15    User(id: 2, name: "Noah"),
16    User(id: 1, name: "Ava Updated")
17]
18
19print(uniqueById(users).map { $0.name })

Be explicit about whether first or last occurrence should be retained.

Handle non-hashable elements

If elements are not hashable and cannot be made hashable, use nested checks with contains(where:). This is slower for large arrays but still useful for small datasets.

For performance-sensitive code, prefer redesigning types to support hashing or use key extraction where possible.

Performance and memory considerations

Set-based approaches are typically linear on average and require additional memory for seen elements. For large arrays, reserve result capacity to reduce reallocations and keep dedupe work off the main thread when running in UI applications.

When deduplicating streaming data, consider incremental dedupe windows instead of storing all historical keys in memory.

Encapsulate dedupe as reusable extension

A reusable extension reduces repeated logic and improves testability.

swift
1extension Array where Element: Hashable {
2    func uniqued() -> [Element] {
3        var seen = Set<Element>()
4        return filter { seen.insert($0).inserted }
5    }
6}
7
8print([1, 1, 2, 3, 2].uniqued())

Shared utility code helps teams avoid inconsistent dedupe behavior across modules.

Add tests for business semantics

Tests should verify more than uniqueness. Assert order preservation, chosen occurrence policy, and behavior on empty arrays. For object arrays, test dedupe key conflicts explicitly.

A small test suite around array utilities prevents subtle regressions during refactors.

Consider memory behavior in long-running sessions

In long-running processes such as data sync workers, dedupe sets can grow unexpectedly if reused across batches. Keep dedupe state scoped to one batch unless cross-batch uniqueness is explicitly required. This avoids hidden memory growth and makes each processing cycle easier to reason about.

Common Pitfalls

  • Using Set conversion when list order must be preserved.
  • Assuming object uniqueness without defining dedupe key.
  • Keeping the wrong occurrence when duplicates conflict on non-key fields.
  • Running large dedupe operations synchronously on the main thread.
  • Copying ad hoc dedupe snippets instead of reusing one tested utility.

Summary

  • Choose dedupe method based on order requirements and data type characteristics.
  • Use Set conversion for fastest unordered uniqueness.
  • Use seen-set iteration for ordered dedupe in most app workflows.
  • Deduplicate complex objects by explicit business keys.
  • Wrap logic in reusable utilities and verify behavior with targeted tests.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.