Как объединить операции filter и map для оптимизации?
Что проверяют
Понимаете ли вы, где на самом деле теряется производительность в цепочке filter и map. Два прохода по массиву дают ту же сложность O(n), дорого другое: промежуточный массив, который выделяется и заполняется между шагами. Следом обычно спрашивают про lazy и когда он вредит.
Как отвечать
Покажите несколько способов и условия, при которых каждый уместен:
compactMap: когда преобразование само может не получиться и возвращает опционал, напримерstrings.compactMap { Int($0) }. Фильтр и преобразование сливаются естественно и без force unwrap;lazy:numbers.lazy.filter { $0 > 0 }.map { $0 * 2 }не создаёт промежуточных массивов, элементы проходят цепочку по одному. Особенно выигрывает сfirst(where:)илиprefix, потому что обработка останавливается, как только результат найден. Если в конце нужен массив, результат оборачивают вArray(...);reduce(into:): один проход с явным накоплением,reduce(into: [Int]()) { acc, x in if x > 0 { acc.append(x * 2) } };- обычный
forсwhere:for x in items where x.isActive { result.append(transform(x)) }плюсreserveCapacity, если примерный размер известен. В горячем коде это часто самый быстрый и понятный вариант.
Обязательно скажите про замеры: сравнивать варианты имеет смысл в Release-сборке через measure в XCTest или в Instruments. В Debug оптимизатор выключен, и цифры не имеют отношения к реальности. На массиве в сотню элементов разницы не будет, и там выбирают самый читаемый вариант.
Где спотыкаются
Утверждают, что compactMap всегда быстрее пары filter и map. Если условие не связано с опционалом, запись compactMap { cond($0) ? f($0) : nil } читается хуже, а выигрыш даёт отсутствие промежуточного массива, а не сам метод.
Сохраняют ленивую последовательность в свойство и обходят её несколько раз. Замыкания выполняются заново при каждом обходе, и «оптимизация» удваивает работу. Особенно опасно, если в map есть побочные эффекты.
Оставляют в коде filter { Int($0) != nil }.map { Int($0)! }. Строка парсится дважды, а force unwrap упадёт при первой же правке условия фильтра.