Swift
iOS Development
Programming
Dictionary Conversion
Swift Arrays

Map Array of objects to Dictionary in Swift

Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms

Introduction

Converting an array of objects to a dictionary is a common Swift operation for fast lookups by key. Swift provides Dictionary(uniqueKeysWithValues:) for arrays with guaranteed unique keys, Dictionary(grouping:by:) for grouping multiple elements under each key, and the reduce(into:) method for custom transformations. The right choice depends on whether keys are unique and what structure you need in the result.

Using Dictionary(uniqueKeysWithValues:)

Transform the array into key-value tuples, then construct the dictionary:

swift
1struct User {
2    let id: Int
3    let name: String
4}
5
6let users = [
7    User(id: 1, name: "Alice"),
8    User(id: 2, name: "Bob"),
9    User(id: 3, name: "Charlie")
10]
11
12// Map to dictionary keyed by id
13let userDict = Dictionary(uniqueKeysWithValues: users.map { ($0.id, $0) })
14print(userDict[2]?.name)  // Optional("Bob")
15
16// Map to dictionary of id -> name
17let nameDict = Dictionary(uniqueKeysWithValues: users.map { ($0.id, $0.name) })
18print(nameDict)  // [1: "Alice", 2: "Bob", 3: "Charlie"]

This crashes at runtime if the array contains duplicate keys. Only use it when you are certain keys are unique.

Handling Duplicate Keys

Use Dictionary(_:uniquingKeysWith:) to resolve conflicts when keys may repeat:

swift
1let items = [("a", 1), ("b", 2), ("a", 3)]
2
3// Keep the first value
4let first = Dictionary(items, uniquingKeysWith: { existing, _ in existing })
5print(first)  // ["a": 1, "b": 2]
6
7// Keep the last value
8let last = Dictionary(items, uniquingKeysWith: { _, new in new })
9print(last)  // ["a": 3, "b": 2]
10
11// Sum the values
12let summed = Dictionary(items, uniquingKeysWith: { $0 + $1 })
13print(summed)  // ["a": 4, "b": 2]

Grouping with Dictionary(grouping:by:)

When multiple elements share a key, group them into arrays:

swift
1struct Product {
2    let name: String
3    let category: String
4}
5
6let products = [
7    Product(name: "iPhone", category: "Electronics"),
8    Product(name: "iPad", category: "Electronics"),
9    Product(name: "Chair", category: "Furniture"),
10    Product(name: "Desk", category: "Furniture"),
11    Product(name: "MacBook", category: "Electronics")
12]
13
14let grouped = Dictionary(grouping: products, by: { $0.category })
15print(grouped["Electronics"]?.count)  // Optional(3)
16print(grouped["Furniture"]?.map(\.name))  // Optional(["Chair", "Desk"])

The result type is [String: [Product]] — each key maps to an array of matching elements.

Using reduce(into:)

For custom dictionary construction logic:

swift
1let words = ["apple", "banana", "avocado", "blueberry", "cherry"]
2
3// Group by first character
4let byLetter = words.reduce(into: [Character: [String]]()) { dict, word in
5    let key = word.first!
6    dict[key, default: []].append(word)
7}
8print(byLetter)
9// ["a": ["apple", "avocado"], "b": ["banana", "blueberry"], "c": ["cherry"]]
10
11// Count occurrences
12let items = ["red", "blue", "red", "green", "blue", "red"]
13let counts = items.reduce(into: [:]) { dict, item in
14    dict[item, default: 0] += 1
15}
16print(counts)  // ["red": 3, "blue": 2, "green": 1]

reduce(into:) is more efficient than reduce for building collections because it mutates in place rather than copying.

Converting Back to Array

swift
1let dict = ["a": 1, "b": 2, "c": 3]
2
3// Dictionary to array of tuples
4let tuples = dict.map { ($0.key, $0.value) }
5print(tuples)  // [("a", 1), ("b", 2), ("c", 3)] (order may vary)
6
7// Dictionary to array of values sorted by key
8let sorted = dict.sorted { $0.key < $1.key }.map(\.value)
9print(sorted)  // [1, 2, 3]

Dictionaries are unordered. Sort explicitly when order matters.

Real-World Example

swift
1struct Employee: Hashable {
2    let id: String
3    let name: String
4    let department: String
5}
6
7let employees = [
8    Employee(id: "E001", name: "Alice", department: "Engineering"),
9    Employee(id: "E002", name: "Bob", department: "Marketing"),
10    Employee(id: "E003", name: "Charlie", department: "Engineering"),
11    Employee(id: "E004", name: "Diana", department: "Marketing")
12]
13
14// Fast lookup by ID
15let byId = Dictionary(uniqueKeysWithValues: employees.map { ($0.id, $0) })
16let alice = byId["E001"]  // Employee(id: "E001", name: "Alice", ...)
17
18// Group by department
19let byDept = Dictionary(grouping: employees, by: \.department)
20let engineers = byDept["Engineering"]!  // [Alice, Charlie]

Common Pitfalls

  • Using uniqueKeysWithValues with duplicate keys: This causes a runtime crash (Fatal error: Duplicate values for key). If keys might repeat, use Dictionary(_:uniquingKeysWith:) to specify a merge strategy.
  • Forgetting that dictionaries are unordered: When you convert an ordered array to a dictionary, the insertion order is not guaranteed when iterating. If order matters, use sorted() on the dictionary or keep a separate ordered collection.
  • Using reduce instead of reduce(into:) for building dictionaries: reduce copies the accumulator dictionary on each iteration, resulting in O(n^2) performance. reduce(into:) mutates in place and runs in O(n).
  • Force-unwrapping dictionary lookups: dict[key]! crashes if the key does not exist. Use optional binding (if let value = dict[key]) or provide a default with dict[key, default: defaultValue].
  • Not using \.keyPath syntax: Instead of { $0.category }, Swift supports \.category in many contexts. Key path expressions are more readable and less error-prone than closure syntax for simple property access.

Summary

  • Use Dictionary(uniqueKeysWithValues:) with .map { (key, value) } when keys are guaranteed unique
  • Use Dictionary(_:uniquingKeysWith:) to handle duplicate keys with a merge strategy
  • Use Dictionary(grouping:by:) to group multiple elements under each key
  • Use reduce(into:) for custom dictionary construction — it is more efficient than reduce
  • Dictionaries are unordered — sort explicitly when iteration order matters
  • Always handle optional dictionary lookups safely with if let or default values

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
Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms