Функции reduce и filter для работы с коллекциями на Swift

В Swift мы можем использовать функции reduce() и filter() для преобразований коллекций без использования циклов.

Функция reduce() превращает коллекцию в одно значение. Функция filter() возвращает значения, если необходимое условие истинно.

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

Функция reduce

Функция reduce(_:_:) перебирает каждый элемент в коллекции и сводит их к одному значению. Воспринимайте ее как способ объединить несколько значений в одно.

Каким образом вы можете перейти от множества значений в коллекции к одному значению? Вот несколько примеров:

  • Подсчет суммы нескольких значений: 3 + 4 + 5 = 12.
  • Конкатенация коллекции строк: [«Дом», «Комната», «Стул»] = «Дом, Комната, Стул».
  • Усреднение набора значений: (7 + 3 + 10) / 3 = 7/3 + 3/3 + 10/3 = 6.667

Вы можете решить любую из этих проблем с помощью цикла for, но с помощью функции reduce(_:_:) ваш код будет гораздо проще и компактней.

let values = [3, 4, 5]
let sum = values.reduce(0, +)
print(sum)
// 12

Функция принимает два аргумента — начальное значение и замыкание. В приведенном выше коде мы используем оператор +.

Вы также можете написать свое собственное замыкание:

let values = [7.0, 3.0, 10.0]
let average = values.reduce(0.0) { $0 + $1 } / Double(values.count)
print(average)
// 6.666666666666667

В приведенном выше примере мы рассчитываем среднее из трех чисел. Все значения имеют тип Double. Сначала мы складываем все числа, а затем делим их на общее количество.

Функция reduce(_:_:) имеет свои особенности:

  1. Функция принимает два параметра: начальное значение и замыкание.
  2. Замыкание также принимает два параметра: текущий результат и новое значение.
let values = [7, 3, 10]
let sum = values.reduce(0) {
    print("\($0) + \($1) = \($0 + $1)")
    return $0 + $1
}
 
print(sum)
// 0 + 7 = 7
// 7 + 3 = 10
// 10 + 10 = 20
// 20

В приведенном примере вы можете четко видеть 2 параметра замыкания — $0 и $1.

Мы начинаем с 0, потом добавляем 7. На следующем шаге мы берем 7 — текущее значение — и добавляем 3 — следующее значение.

Функция filter

Функция filter() перебирает каждый элемент в коллекции и возвращает новую коллекцию, которая содержит только те элементы, которые удовлетворяют поставленным условиям. Это все равно, что применять if условие к коллекции и сохранять только те значения, которые проходят проверку.

let values = [11, 13, 14, 6, 17, 21, 33, 22]
let even = values.filter { $0.isMultiple(of: 2) }
print(even)
// [14, 6, 22]

В приведенном примере мы фильтрум четные числа из массива values. Функция isMultiple(of:) возвращает true, когда текущее значение можно разделить на 2. В противном случае возвращается false.

В отличие от функций map(_:) и reduce(_:_:) функция filter(_:) должна возвратить либо true либо false. Когда замыкание возвращает true, значения сохраняются, а когда возвращается false, значения опускаются.

Мы можем расписать данное замыкание более подробно:

let values = [11, 13, 14, 17, 21, 33, 22]
let even = values.filter({ (value: Int) -> Bool in
    return value.isMultiple(of: 2)
})
 
print(even) 
// [11, 13, 17, 21, 33]

Группировка нескольких функций

Вы также можете объединять несколько функций высшего порядка.

Допустим, у нас есть класс студентов. Вы знаете год, когда родился каждый студент. Вы хотите рассчитать совокупный возраст всех учащихся, родившихся в 2000 году или позже.

let now = 2020
let years = [1989, 1992, 2003, 1970, 2014, 2001, 2015, 1990, 2000, 1999]
let sum = years.filter({ $0 >= 2000 }).map({ now - $0 }).reduce(0, +)
print(sum)
// 67

В приведенном выше примере кода используется связывание нескольких функций. Данный код использует результат одной функции в качестве входных данных для другой.

Читайте также:
Добавить комментарий

Ваш адрес email не будет опубликован.