При преобразовании массива функция иногда возвращает nil: чем будут отличаться результаты применения map и compactMap?
map сохраняет один результат на каждый исходный элемент, поэтому значения nil останутся в результирующем массиве. compactMap исключает nil и возвращает только успешно преобразованные значения, поэтому размер результата может уменьшиться.
Функциональные операции над коллекциями разделяют преобразование данных и отбор результата. Проблема возникает, когда преобразование может завершиться неуспешно: обычный map сохраняет неуспех как nil, а вызывающему коду часто нужен сразу массив только корректных значений.
compactMap предназначен для объединения преобразования и удаления пустых результатов без ручного промежуточного хранения optional-значений.
Предположим, строки преобразуются в числа, но часть строк имеет неверный формат. Использование map даст массив типа [Int?]: каждый исходный элемент представлен в результате, включая неудачные преобразования.
Если передать такой массив дальше как [Int], потребуется отдельно обработать nil. Ошибочный выбор операции может привести к лишним проверкам, случайному разыменованию optional или неверному подсчёту количества успешно обработанных элементов.
map применяет замыкание ко всем элементам и сохраняет каждый возвращённый результат. Если замыкание возвращает Int?, результатом будет [Int?]; позиция каждого элемента сохраняется.
compactMap также применяет замыкание к элементам, но добавляет в результат только значения, отличные от nil. Поэтому результатом будет [Int], а порядок успешно преобразованных элементов сохранится.
compactMap удаляет только nil. Ноль, пустая строка, false и другие значения, не являющиеся nil, сохраняются. Операция также не удаляет вложенные optional автоматически: она отбрасывает результат, который на проверяемом уровне равен nil.
Выбирайте map, когда соответствие позиций важно или nil несёт полезную информацию. Выбирайте compactMap, когда неуспешные преобразования нужно трактовать как отсутствие элемента и размер результата должен отражать только успешные операции.
В приложении из параметров URL нужно получить идентификаторы объектов. Вариант с map создаёт [Int?], после чего приходится отдельно фильтровать и извлекать значения. Его плюс — сохранение связи между исходной строкой и результатом, что полезно для диагностики ошибок; минус — optional-значения продолжают проходить через последующие слои.
Вариант с filter после преобразования требует сначала получить [Int?], затем проверить каждый optional и извлечь его содержимое. Это явно, но создаёт промежуточное представление и увеличивает объём кода.
Выбран compactMap, потому что задача состоит именно в получении списка корректных идентификаторов, а позиции некорректных строк не нужны. В результате следующий код получает [Int], а число элементов сразу соответствует числу успешно распознанных идентификаторов.
Нет. compactMap сохраняет относительный порядок успешно преобразованных значений, но удаляет позиции, где результатом был nil. Поэтому индекс элемента в результате не обязан совпадать с его индексом в исходной коллекции.
Если связь с исходной позицией важна, нужно сохранить её явно, например преобразовывать пары из индекса и значения либо использовать map, оставляя optional-результаты. Нельзя восстанавливать исходные позиции по одному только результату compactMap.
Нет. Условие удаления — только равенство результата nil. Значения 0, "" и false являются допустимыми результатами и попадут в итоговую коллекцию.
Если требуется отбрасывать значения по дополнительному условию, его нужно выразить в самом преобразовании или применить отдельный filter. Это уже другая логика, не встроенная в compactMap.
Нет. compactMap лучше выражает случай, когда отсутствие результата является частью преобразования. Но если после преобразования нужно отбирать элементы по сложному условию, зависящему от самого значения, исходной позиции или нескольких полей, отдельные операции могут быть понятнее.
Кроме того, map сохраняет информацию о неудачных преобразованиях, а compactMap её теряет. Поэтому выбор определяется не только краткостью, но и тем, нужна ли последующая диагностика причин, по которым элементы были исключены.