Как и когда их использовать

В обычном приложении очень часто приходится работать с массивами. Часто нам нужно взять все элементы один за другим и применить к ним некоторые преобразования.

Это происходит очень часто, и я вижу, что многие младшие или средние разработчики выполняют эту задачу, используя классическую итерацию, с чем-то вроде forEach, не зная, что есть лучшие функции для решения этой проблемы прямо во фреймворке Foundation.

карта

Карта — это стандартная функция Swift, используемая для коллекции, которая принимает на вход замыкание, применяемое к каждому элементу, и возвращает другую коллекцию. Другими словами, у вас есть начальный массив, вы берете все элементы массива один за другим, применяете к каждому из них преобразование, управляемое вашим замыканием, и добавляете полученное значение в новый массив.

Хорошо, давайте сделаем пример. Допустим, мы хотим создать игру, в которой игроку даются анаграммы имён героев Marvel, и он/она должен угадать правильного персонажа. У нас есть список имен, и мы должны применить следующие шаги к каждому элементу списка:

  1. Преобразование имен в нижний регистр
  2. Удалить пробелы
  3. Перемешайте буквы

Без 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]], как в предыдущем примере.

Надеюсь, вам понравилась эта статья, если да, пожалуйста, хлопните в ладоши.
Если эта статья была вам полезна, не стесняйтесь предложить мне кофе и позвольте мне создать больше классного контента и статей.

Наслаждайтесь кодированием!