Как и когда их использовать
В обычном приложении очень часто приходится работать с массивами. Часто нам нужно взять все элементы один за другим и применить к ним некоторые преобразования.
Это происходит очень часто, и я вижу, что многие младшие или средние разработчики выполняют эту задачу, используя классическую итерацию, с чем-то вроде forEach
, не зная, что есть лучшие функции для решения этой проблемы прямо во фреймворке Foundation
.
карта
Карта — это стандартная функция Swift, используемая для коллекции, которая принимает на вход замыкание, применяемое к каждому элементу, и возвращает другую коллекцию. Другими словами, у вас есть начальный массив, вы берете все элементы массива один за другим, применяете к каждому из них преобразование, управляемое вашим замыканием, и добавляете полученное значение в новый массив.
Хорошо, давайте сделаем пример. Допустим, мы хотим создать игру, в которой игроку даются анаграммы имён героев Marvel, и он/она должен угадать правильного персонажа. У нас есть список имен, и мы должны применить следующие шаги к каждому элементу списка:
- Преобразование имен в нижний регистр
- Удалить пробелы
- Перемешайте буквы
Без map
с использованием forEach
, например, вам нужно было бы для каждого шага, конечно, создать пустой массив, применить шаг к каждому элементу и добавить результат... три массива, слишком много материала и довольно сложно читать и понимать. Давайте посмотрим, насколько многословен этот подход:
Используя вместо этого map
, все очень просто и читабельно. Это просто как волшебство!
Как видите, это очень читабельно, даже если вы не знаете всех необходимых шагов.
Компактная карта
CompactMap
работает аналогично карте, но с бонусом… он удаляет все nil
элементов, заданных преобразованием.
Давайте посмотрим на быстрый пример:
Как видите, смайлик не может создать действительный URL. С помощью compactMap
вы можете фильтровать его без каких-либо проблем или других проверок.
CompactMap
также является отличным способом отфильтровать список, чтобы удалить любое значение nil
. Недавно я работал над приложением, в котором все метки пользовательского интерфейса одного контроллера представления управлялись данными, отправленными сервером. Если значение было там, вы должны были показать метку, если нет, метка будет скрыта, не оставляя пустого места.
В UITableView
все было динамично, поэтому мне нужно было только добавить элемент или нет в источник данных (если вам интересна моя личная техника работы с источниками данных и разделами взгляните на эту статью) .
Что ж, фильтрация всего с помощью compactMap
была супер быстрой и супер читаемой. Что-то вроде этого, конечно, в приложении было немного сложнее:
Обратите внимание на одну вещь в последнем примере. Массив полей имеет тип [String?]
, а массив элементов имеет тип [String]
, поэтому возвращаемый тип compactMap
никогда не будет optional
. Ух ты, потрясающе!
Плоская карта
Последний тип карты — это функция, которая, как следует из названия, сглаживает массив массивов. Он просто преобразует серию массивов в один за один проход, примерно так:
[[1, 1, 1], [2, 2, 2], [3, 3, 3]] -> [1, 1, 1, 2, 2, 2, 3, 3, 3]
Давайте сделаем пример.
Вы программируете одну из тех игр с отрядами боевых героев. В вашей команде есть группа персонажей, и вы сами решаете, кто сражается в каждой игре.
В каждом раунде к характеристикам играющего героя добавляется количество побежденных врагов. Теперь вам нужно рассчитать среднее количество побежденных врагов за раунд вашего отряда, поэтому в основном вам нужно создать единый массив всех характеристик всех героев и узнать среднее значение.
Давайте посмотрим на код:
Вся магия выполняется в строке 25. Обратите внимание, что я использовал расширение для вычисления среднего значения (строка 26) вместо функции vDSP.mean
(ссылка здесь) фреймворка Accelerate
, чтобы сохранить красивое функциональное программирование. стиль.
Еще кое-что
Если вы внимательно читали начало статьи, то могли заметить, что я написал о коллекциях, а не о простых массивах. Ты знаешь почему? Потому что функции карты можно применять и к словарям! При любом способе использования этих функций со словарями требуется особая осторожность:
Как видно из примера, исходный словарь разбит на массив словарей. Теперь вы можете применить преобразование только к значениям словаря, а не к ключам.
Ну, знаешь что? У Swift есть серия карт для всех трех предыдущих вариантов для выполнения этой задачи! Просто используйте версию mapValues
:
Как видите, в результате получается [String: String]
, а не [[String: String]]
, как в предыдущем примере.
Надеюсь, вам понравилась эта статья, если да, пожалуйста, хлопните в ладоши.
Если эта статья была вам полезна, не стесняйтесь предложить мне кофе и позвольте мне создать больше классного контента и статей.
Наслаждайтесь кодированием!