> Можно ли объединить массивы через reduce (iOS, Swift)

Уровень: senior · Роль: mobile · Категория: Технические вопросы

Компании: Яндекс

Стек: iOS, Swift

> Пример ответа

Короткий ответ

Да, можно. reduce - универсальная функция высшего порядка, которая позволяет свести последовательность к любому типу результата, включая массив. Для объединения массивов используется reduce(into:) с += или +, но на практике для этой задачи лучше подходит flatMap/compactMap - они читаемее и не создают лишних промежуточных копий.

Подробное объяснение

reduce принимает начальное значение и замыкание, которое на каждом шаге получает аккумулятор и текущий элемент. Возвращаемый тип аккумулятора не обязан совпадать с типом элемента последовательности - поэтому можно "накапливать" массив.

Для объединения массивов есть два варианта:

  • reduce(into:) - мутирует аккумулятор на месте, что эффективнее по памяти.
  • reduce с + - создаёт новую копию массива на каждой итерации, что приводит к O(n²) по времени.

Однако для простого объединения массивов reduce избыточен. Стандартная библиотека предоставляет joined() для [[Element]] и flatMap для произвольных вложенных коллекций. reduce оправдан, когда нужно объединить массивы с дополнительной логикой - фильтрацией, трансформацией или условием.

На практике

В продакшене для объединения массивов используйте flatMap или joined(). reduce(into:) применяйте, когда нужно одновременно агрегировать и модифицировать элементы, например, собирать только чётные числа из нескольких массивов или строить словарь с группировкой.

Пример кода

SWIFT
let arrays = [[1, 2], [3, 4], [5]]
// Через reduce(into:) - эффективно
let flattened = arrays.reduce(into: [Int]()) { result, array in
result += array
}
// Через reduce с + - неэффективно, O(n²)
let slow = arrays.reduce([Int]()) { $0 + $1 }
// Лучший вариант для простого случая
let best = arrays.flatMap { $0 }
// reduce с логикой: только чётные
let evens = arrays.reduce(into: [Int]()) { result, array in
result.append(contentsOf: array.filter { $0 % 2 == 0 })
}

Как отвечать на собеседовании

Начните с прямого ответа "да", затем покажите два синтаксиса - reduce и reduce(into:). Обязательно упомяните сложность: reduce с + квадратичная, reduce(into:) линейная. После этого скажите, что для простого объединения лучше flatMap, и объясните, когда reduce действительно уместен - при дополнительной логике. Если спросят про производительность, добавьте про копирование массивов и COW (copy-on-write).

Что проверяет интервьюер

Интервьюер оценивает:

  • понимание сигнатуры reduce и гибкости аккумулятора;
  • знание reduce(into:) и его преимуществ;
  • умение выбирать правильный инструмент, а не использовать reduce везде;
  • осознание сложности алгоритмов и работы с памятью в Swift.

Типичные ошибки

  • Использование reduce с + для больших массивов - квадратичная сложность.
  • Забывают про reduce(into:), который существует именно для мутирующих аккумуляторов.
  • Применяют reduce там, где flatMap или joined() решают задачу проще и читаемее.
  • Путают flatMap со compactMap - последний не разворачивает вложенные массивы, а отбрасывает nil.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью