> Как реализовать фильтрацию массива с сохранением уникальных элементов и порядка (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: 2GIS
Стек: iOS, Swift
> Пример ответа
Короткий ответ
Для фильтрации массива с сохранением уникальных элементов и порядка в Swift используйте NSOrderedSet для простых случаев или комбинацию Set и filter для контроля над логикой. Основной подход - проходим по массиву, добавляем элементы в Set для отслеживания дубликатов и оставляем только те, которые встречаются впервые. Это гарантирует сохранение исходного порядка и O(n) сложность.
Подробное объяснение
Задача сводится к удалению дубликатов без изменения порядка элементов. Ключевая идея - использовать вспомогательную структуру данных для быстрой проверки уникальности. Set в Swift обеспечивает константное время доступа, поэтому алгоритм работает за O(n).
Основные подходы:
-
NSOrderedSet- готовое решение из Foundation, сохраняет порядок и уникальность. Минус - требует преобразования типов и работает только сHashableэлементами. -
Ручная реализация с
Set- более гибкий вариант. Создаём пустойSet, затем фильтруем массив, проверяя, был ли элемент уже добавлен. Если нет - добавляем и оставляем в результате. -
reduceс кортежем - функциональный стиль, но менее читаемый и менее эффективный из-за создания промежуточных структур.
Для элементов, не соответствующих Hashable, можно использовать NSObject или кастомную логику сравнения через Equatable с ручным поиском (O(n²) - не рекомендуется для больших массивов).
На практике
В реальных проектах чаще всего используется вариант с Set, так как он:
- не требует импорта Foundation (если не нужен
NSOrderedSet); - работает с любыми
Hashableтипами; - легко расширяется (например, можно добавить условие фильтрации по свойству объекта).
Для массивов структур или классов с идентификаторами удобно фильтровать по id, а не по всему объекту - это ускоряет проверку уникальности.
Пример кода
SWIFT// Базовый вариант для Hashable элементовextension Array where Element: Hashable {func unique() -> [Element] {var seen = Set<Element>()return filter { element inif seen.contains(element) {return false} else {seen.insert(element)return true}}}}let numbers = [1, 2, 3, 2, 4, 1, 5]print(numbers.unique()) // [1, 2, 3, 4, 5]// Вариант с фильтрацией по свойствуstruct User {let id: Intlet name: String}let users = [User(id: 1, name: "Alice"),User(id: 2, name: "Bob"),User(id: 1, name: "Alice Again")]var seenIDs = Set<Int>()let uniqueUsers = users.filter { user inguard !seenIDs.contains(user.id) else { return false }seenIDs.insert(user.id)return true}print(uniqueUsers.map { $0.name }) // ["Alice", "Bob"]
Как отвечать на собеседовании
Начните с простого решения через Set, объясните сложность O(n). Затем упомяните альтернативы: NSOrderedSet для быстрого прототипирования и reduce для функционального стиля. Подчеркните важность сохранения порядка - это ключевое отличие от простого использования Set для дедупликации. Если спросят про не-Hashable элементы, предложите вариант с Equatable и объясните trade-off по производительности.
Что проверяет интервьюер
- Понимание структур данных и их временной сложности.
- Умение работать с дженериками и расширениями в Swift.
- Способность учитывать edge cases: пустой массив, все элементы уникальны, все дубликаты.
- Знание альтернативных подходов и их ограничений.
Типичные ошибки
- Использование
Set(array)напрямую - теряется порядок. - Забывают про
Hashableограничение и пытаются применить к произвольным типам. - Реализация через
containsвнутриfilter- даёт O(n²) и падает на больших данных. - Не учитывают, что
NSOrderedSetтребует импорта Foundation и работает медленнее на больших массивах из-за мостов с Objective-C.
> Похожие задачи по mobile
Как реализовать проверку на переполнение при конвертации строки в число
Как разделить функции для чтения и записи значений
Как реализовать функцию setValue для обновления значения по ключу
Какой следующий этап после технического интервью
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью