Чем отличается compactMap от flatMap?ios-39

Исторический контекст

В Swift 4.1 появилось разделение flatMap на два отдельных метода:

  1. flatMap - для "разглаживания" коллекций
  2. compactMap - для работы с опционалами

Это изменение было внесено для устранения двусмысленности в использовании flatMap.

1. flatMap - для работы с вложенными коллекциями

Назначение: Преобразует и объединяет (разглаживает) коллекции коллекций в одну плоскую коллекцию.

let nestedArrays = [[1, 2, 3], [4, 5, 6]]
let flattened = nestedArrays.flatMap { $0 }
// Результат: [1, 2, 3, 4, 5, 6]

Ключевые особенности:

  • Работает с коллекциями коллекций
  • "Разглаживает" вложенность на один уровень
  • Сохраняет все элементы, включая дубликаты

2. compactMap - для работы с опционалами

Назначение: Трансформирует элементы коллекции с автоматической фильтрацией nil значений.

let strings = ["1", "2", "three", "4"]
let numbers = strings.compactMap { Int($0) }
// Результат: [1, 2, 4] ("three" отфильтровано)

Ключевые особенности:

  • Отфильтровывает nil значения
  • Возвращает массив неопциональных значений
  • Эквивалентен map + filter nil в одном методе

Сравнительная таблица

ХарактеристикаflatMapcompactMap
Входные данные Коллекция коллекций Коллекция опционалов
Результат "Разглаженная" коллекция Коллекция без nil
Фильтрация nil Нет Да
Swift версия Все версии С 4.1
Использование Работа с вложенностями Преобразование + фильтр

Примеры из практики

1. Обработка сетевых ответов

// compactMap идеален для парсинга
let responses = ["200", "404", "500", "invalid"]
let statusCodes = responses.compactMap { Int($0) }
// [200, 404, 500]

2. Работа с многомерными данными

// flatMap для объединения данных
let departments = [
    ["Alice", "Bob"],
    ["Charlie", "Diana"]
]
let allEmployees = departments.flatMap { $0 }
// ["Alice", "Bob", "Charlie", "Diana"]

3. Комбинирование методов

let matrix = [[1, nil, 3], [nil, 5, 6]]
let values = matrix.flatMap { $0.compactMap { $0 } }
// [1, 3, 5, 6]

Почему было разделено?

До Swift 4.1 flatMap использовался для обоих сценариев, что приводило к:

  1. Неочевидности кода
  2. Сложностям в понимании
  3. Потенциальным ошибкам при рефакторинге

Рекомендации по использованию

  1. Для работы с опционалами всегда используйте compactMap
  2. Для "разглаживания" коллекций используйте flatMap
  3. В коде до Swift 4.1 замените flatMap на compactMap где работаете с опционалами

Резюмируем

  • flatMap предназначен для разглаживания коллекций коллекций в одну плоскую структуру
  • compactMap используется для трансформации с фильтрацией nil значений
  • Разделение было введено в Swift 4.1 для улучшения ясности кода
  • Выбор метода зависит от типа решаемой задачи (работа с вложенностями vs обработка опционалов)

Правильное использование этих методов делает код более выразительным и безопасным.