Swift
iOS Development
Programming
Dictionary Conversion
Swift Arrays

Map Array of objects to Dictionary in Swift

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

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 illustration
Course illustration

All Rights Reserved.