Собственные функции высшего порядка
Часть раздела Логика и управление потоком путешествия по Swift на Coddy — урок 42 из 56.
Теперь вы можете писать свои собственные функции высшего порядка, и они отлично впишутся в ряд с map и filter. Структура всегда одна и та же: принимаете параметр-замыкание, вызываете его внутри цикла, возвращаете результат.
extension Array {
func myMap<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
for item in self {
result.append(transform(item))
}
return result
}
}
[1, 2, 3].myMap { $0 * 10 } // [10, 20, 30]Если расширения кажутся избыточными, напишите вместо них свободную функцию, идея остается той же:
func count<T>(_ items: [T], where predicate: (T) -> Bool) -> Int {
var n = 0
for item in items where predicate(item) {
n += 1
}
return n
}Как только вы научитесь передавать замыкания, стандартная библиотека перестает казаться магией и начинает выглядеть как набор паттернов, которые вы могли бы написать сами.
Задание
СреднеНапишите свободную функцию partition(_ items: [Int], by predicate: (Int) -> Bool) -> ([Int], [Int]), которая один раз обходит массив и возвращает кортеж (matched, rest): элементы, удовлетворяющие предикату, и остальные элементы, оба списка в исходном порядке.
Прочитайте две строки: целое число min, затем список целых чисел, разделенных запятыми. Используйте вашу функцию partition с предикатом, который проверяет n > min. Выведите:
matched: <...>rest: <...>
Каждый список должен быть объединен через , (или быть пустым, если выводить нечего).
Для входных данных 5 / 2,7,3,8,5 результатом будет:
matched: 7,8
rest: 2,3,5Шпаргалка
Функции высшего порядка следуют единому шаблону: принимают замыкание, вызывают его в цикле и возвращают результат.
В виде расширения:
extension Array {
func myMap<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
for item in self {
result.append(transform(item))
}
return result
}
}
[1, 2, 3].myMap { $0 * 10 } // [10, 20, 30]В виде свободной функции:
func count<T>(_ items: [T], where predicate: (T) -> Bool) -> Int {
var n = 0
for item in items where predicate(item) {
n += 1
}
return n
}Функция partition, возвращающая кортеж из совпавших и несовпавших элементов:
func partition(_ items: [Int], by predicate: (Int) -> Bool) -> ([Int], [Int]) {
var matched: [Int] = []
var rest: [Int] = []
for item in items {
if predicate(item) { matched.append(item) }
else { rest.append(item) }
}
return (matched, rest)
}Попробуйте сами
let min = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }
// TODO: partition(_:by:) -> ([Int], [Int]); вывести подходящие и остальные
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Логика и управление потоком
1Строки в деталях
Подсчет и индексыРегистр и удаление пробеловПоиск в строкахРазделение и объединениеЗамена подстрокИтоги — Проверка имени пользователя4Множества
Создание множествОбъединение и пересечениеРазность и симметрическая разностьПодмножество и надмножествоИтоги — Фильтр тегов7Проект — Трекер привычек
Обзор проектаОтметить выполнение10Проект — Движок викторины
Обзор проектаЗадаем вопросы2Диапазоны и шаги
Закрытые и полуоткрытыеШагМетоды диапазоновДиапазоны в SwitchИтоги: Сетка календаря8Замыкания
Основы замыканийПоследующие замыканияЗахват значенийВозврат замыканийСобственные функции высшего порядкаИтоги — Pipeline Builder